Files
palemoon27/browser/components/shell/nsWindowsShellService.cpp
T
roytam1 25a43ca130 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1252882 - Content-Signature Service - some tests r=keeler,r=fkiefer (7fc1f726a4)
- Bug 1265085 - Replace verification source with a SAN in the content signature verifier interface. r=Cykesiopka,r=fkiefer (0881ba797d)
- Bug 1242820 - Disable devtools/shared/security/tests/unit/test_oob_crt_auth.js and test_encryption.js on emulator-x86-kk; r=jryans (746802bb0e)
- Bug 1264706: Move nsILocalCertService, and implementation, to security/manager/ssl in order to alloow use w use elsewhere in gecko. r=dkeeler (6f2200f2a6)
- Bug 1219088 - Clear the session cache when a weak crypto override is revoked. r=keeler (456e2ce3e6)
- Bug 550185 - Ensure nsCertTree::GetCellText returns an initialized value. r=kaie (ee356452a5)
- Bug 1252384 - Remove nsICertTree.isHostPortOverride(). r=dkeele It is unused since the changes in Bug 825583 landed. (61400adad7)
- reorder as Bug 1411458 (600fc338a9)
- bug 1264761 - improve handling of x509 versions in certificate manager r=Cykesiopka (a89237c66d)
- Bug 1263857 - (followup) Disable windows crash reporter on automated tests. r=sfink (bb9581fec9)
- bug 1263221 - improve how PSM handles the visibility of __CERT_AddTempCertToPerm r=chmanchester,mgoodwin (d9fd09d9a6)
- bug 1182742 - allow users to override small key size errors r=rbarnes (b09074987b)
- Bug 1252722 - Fully implement nsNSSShutDownObject everywhere. r=keeler (8c1a8df597)
- Bug 1252722 - Use smart pointers for NSS resources. r=keeler (b2ef34f9d2)
- Bug 1252722 - Ensure arguments of all public methods are checked. r=keeler (7064697e25)
- bug 1242032 - change some pipnss logging output from Debug to Verbose r=Cykesiopka (516c52da9f)
- Bug 1252722 - Improve handling of PK11_* function error codes. r=keeler (b47d13bd7e)
- Bug 1251801 - Ensure arguments of all public methods are checked. r=keeler (ffe77174e7)
- Bug 1127158 - Remove brittle debug only flag math in nsSecureBrowserUIImpl.cpp. r=dkeeler (410d25dc3e)
- Bug 1257246: Update security/manager for eslint 2. r=cykesiopka (bbdcf78264)
- bug 1218515 - flip pinning-test.badssl.com into production mode r=jcj DONTBUILD NPOTB (0d93e78cab)
- Bug 1199624 - Don't use memset and memcmp in files that don't include cstring explicitly. r=briansmith (5a938e056c)
- Bug 1154399 - Part 1: De-templatize and un-inline IntegralValue. r=keeler (bcaa11a646)
- Bug 1154399 - Part 2: Simplify and un-inline OptionalVersion. r=keeler (a5a9bb5e46)
- Bug 1154399 - Part 3: Simplify OptionalExtensions. r=keeler (0d3f613cde)
- Bug 1154399 - Part 4: Simplify certificate parsing in OCSP responses. r=keeler (94aa90a96d)
- Bug 1189020 - Replace |// unnamed namespace| with |// namespace| in mozilla::pkix. r=Cykesiopka (bb016e13ac)
- bug 1255153 - (re)move redundant xpcshell name constraint tests to gtests r=Cykesiopka,jcj (d8597a3bb1)
- bug 1248099 - add extended key usage tests for mozilla::pkix r=Cykesiopka,jcj (f9c11a8ecc)
- Bug 1266298 - Add sys_fchmod to seccomp whitelist r=jld (e16608d738)
- Bug 1268579 - Add inotify_rm_watch to the seccomp-bpf whitelist. r=jld (c20823e237)
- Bug 1176099 - Add hooks for sigprocmask/pthread_sigmask. r=jld r=glandium (55d16a8e41)
- Bug 1176099 - Fix missing NULL check r=luke (2f6e6e3836)
- Bug 1245789 - Use ifdef MOZ_WIDEVINE_EME to prevent compilation when not enabled. r=gerald (40d13ca2d9)
- Bug 1267453 - Amazon Widevine rejects HDCP on MacBook Pro with or without an external display. r=gcp (5366006c54)
- Bug 1268379 - Delay WMF checks in GMPParent - r=jesup (0f6642fdcc)
- bit of Bug 1245789 - Push detection of WMF decoding (e60b0634de)
- missing bit of 1267453 (573b867a62)
- Bug 1243594 (part 3) - leave the utf-8 encoding of the payload to rest.js instead of directly in loop. r=Standard8 (7781df1275)
- Bug 1243594 (part 2) - have rest.js automatically encode the request body as utf-8. r=gfritzsche (fd98dddf43)
- Bug 1246938 - Allow extra headers to be passed via hawk requests. r=markh (3692244524)
- Bug 1239354: Replace old-style generator function with star functions. r=asuth (a7793a89aa)
- Bug 1217982 - Remove for-each from storage/. r=mak (bbff0f0b7b)
- Bug 1095739 - Allow a "new user" experience to happen subsequent to Firefox being uninstalled. r=gijs r=jimm (2d846f8338)
- Bug 1251819 - Use the classic Control Panel if the Settings app believes the current Windows logon is a Microsoft account while actually it is not. r=jimm (e93f2cac88)
- Bug 1258728 - keep remote newtab version in a pref r=ursula (6f9bacf2ac)
- Bug 1223510, part 1 - Always finishTest() in test_nonUnicode.html. r=baku (ba3fb681ad)
- Bug 1223510, part 2 - Make ArchiveReader tests use pushPrefEnv. r=baku (5a4a5f9a7a)
- Bug 1223510, part 3 - Change where generator is created. r=baku Mostly this lets us take advantage of things created during the initial setup. (ee337d83de)
- Bug 1220304 - Part 1 - Make test_XHRSendData.html use SpecialPowers.createFiles(). r=baku (91fc25f3b7)
- Bug 1220304 - Part 2 - Make ArchiveReader tests use SpecialPowers.createFiles(). r=baku (5a0bfc4200)
- Bug 1267966 - Remove the deprecation warning from Attr.ownerElement; r=baku (cfd8910f2f)
- Bug 1269646 - Console API should be NOP after window-inner-destroyed, r=smaug (c4e5959d1f)
- Bug 1263392 - ConsoleCallData::mStatus should be set also when ConsoleCallData is not used in workers, r=smaug (10358e33a1)
- Bug 1268361 - Strip leading '?' in new URLSearchParams(query), r=smaug (a1a5075185)
- Bug 1052139 - Make more objects on the global prototype chain have immutable [[Prototype]], when we enable enforcement of this requirement. r=bz (8e48cfc3d6)
- Bug 1267932 - Update EventSource.webidl, r=ehsan (41532a54d5)
- Bug 1269383 - Remove dom.server-events.enabled pref, r=smaug (21e65b8436)
- Bug 1237077 - Part 1: drag an URL into new tab should inherit userContextId. r=Gijs, tanvi (f27d38ef25)
- Bug 1237077 - Part 3: use createCodebasePrincipal. r=tanvi (7da7268d47)
- Bug 1264270 - Parser should output attributes in source order, not reversed; r=hsivonen,bgrins (2f78eda012)
- Bug 1268721, part 1 - Use early continue in TransferableToIPCTransferable. r=jimm (317ab04f38)
- Bug 1268721, part 2 - Null check first argument to nsContentUtils::GetSurfaceData(). r=jimm (544d181021)
- Bug 1272203 (part 3) - Use NotNull in nsContentUtils::GetSurfaceData(). r=froydnj. (65e488c4f8)
- Bug 1272203 (part 1) - Add mozilla::NotNull to MFBT. r=froydnj. (4653d120fc)
- Bug 964092: don't let DOM DataChannels get GC'd if they have an active callback r=smaug,jib (c9c291f44a)
- Bug 1224186: Implement DOMTokenlist.replace r=baku,Ms2ger (329f4f942e)
- Bug 1265715 - Part 1. Pull Mode out of nsDisplayListBuilder; r=jfkthame (2c7cae0f3a)
- Bug 1265715 - Part 2. Add nsDisplayListBuilderMode parameter into nsLayoutUtils::PaintFrame; r=jfkthame (5ecabbda5d)
- Bug 1264949 - Ensure that the display list does not contain any background-image/background-color display item; r=jfkthame (018a7aec15)
- Bug 1265715 - Part 3. Use nsLayoutUtils::PaintFrame in ClipBackgroundByText; r=jfkthame (182a700fa6)
- Bug 1265715 - Part 4. Fix transform problem; r=jfkthame (37f77bf24b)
- Bug 1265715 - Part 5. bg-clip:text transform reftest; r=jfkthame (44778bcfd7)
- Bug 1267209 - Convert nsLayoutUtils::PaintFrame flags to be an enum class. r=jfkthame (4f304b84f1)
- Bug 1267530 part 1 - Add some profiler marker for fullscreen transition. r=smaug,BenWa (3580b0a556)
- Bug 1267530 part 2 - Add ASCII art explaination of flow of fullscreen transition. r=smaug (6bee4c9db6)
- Bug 1265280 - Temporary debugging code to crash with a useful abort message. r=khuey (43d532166f)
- Bug 1232939 - Ensure the opaque region of a fixed background layer is correctly clipped. r=mstange (cc2118e0a0)
- Bug 735857 - Treat background-attachment:fixed as background-attachment:scroll if it's on a non-root element affected by a transform. r=mstange (273d62aabf)
- Bug 735857 - Factor out a helper function nsLayoutUtils::IsTransformed(). r=mstange (61528fafef)
- Bug 1263286 - Move base-uri CSP check into SetBaseURIUsingFirstBaseWithHref. r=bz (03114b2fcb)
- Bug 1227327 - Allow specifying a background rect for background dislay items. r=mattwoodrow (410ef269eb)
- Bug 1227327 - Make fieldset frames build nsDisplayBackgroundImage items. r=mattwoodrow (9a3a8953b4)
- Fix temporary debugging patch for bug 1265280 so we'll hit the condition. r=khuey (fd30f8f0b4)
- Bug 1265715 - followup - Correct dirty region; r=me (38fc76e698)
- Bug 550426 - Use background-position-x/y in ActiveLayerTracker. r=dbaron (4f154a39dd)
- Bug 1266131 part 1 - [css-grid] 'order' doesn't apply to grid-aligned abs.pos. descendants (anymore). r=dholbert (ba8aa18fea)
- Bug 1266131 part 2 - [css-grid] Remove unused nsDisplayList::SortByCSSOrder() function. r=dholbert (b676c48a26)
- Bug 550426 - Add support for {background,mask}-position-{x,y}, most of the style system changes. r=dbaron (3739a8ec58)
- Bug 550426 - Add support for {background,mask}-position-{x,y}, StyleAnimation changes. r=dbaron (0fd2f97a60)
- Bug 852754 - Part 4: Reduce max downscaling allowed to <3. r=mstange (399b851221)
- Bug 1266868, part 1 - Fix nsCSSValue::Array leaks in the StyleAnimationValue code. r=dholbert (c6fc4f7d9c)
- Bug 1266868, part 2 - Fix leaks of the values passed to nsCSSValue::.SetPairValue in the StyleAnimationValue code. r=dholbert (e5a1ff8603)
- Bug 1266868, part 3 - Avoid Maybe::ref() where not necessary. r=dholbert (8dd435fd5e)
- Back out bug 1164227, because bug 1236043 fixes the original problem in a better way. (6b734f0718)
- Bug 1267524 Part 1 - Use member initializer list for nsStyleOutline. r=heycam (d7cabb2ea8)
- Bug 1267524 Part 2 - Use member initializer list for nsStyleXUL. r=heycam (82107506a6)
- Bug 1267524 Part 3 - Use member initializer list for nsStyleColumn. r=heycam (80318b0056)
- Bug 1267524 Part 4.1 - Add Reset() and rewrite methods for nsStyleSVGPaint. r=heycam (02ba8762cb)
- Bug 1267524 Part 4.2 - Use member initializer list for nsStyleSVG. r=heycam (5531ed4a93)
- Bug 1267524 Part 5 - Use member initializer list for nsStyleSVGReset. r=heycam (4a72005b1b)
- Bug 1267524 Part 6 - Use member initializer list for nsStylePosition. r=heycam (cfd6a8b640)
- Bug 1267524 Part 7 - Use member initializer list for nsStyleTable. r=heycam (510678ed8b)
- Bug 1267524 Part 8 - Use member initializer list for nsStyleTableBorder. r=heycam (c1617af193)
- Bug 1267524 Part 9 - Use member initializer list for nsStyleColor. r=heycam (753afba9f8)
- Bug 1267524 Part 10 - Use member initializer list for nsStyleDisplay. r=heycam (a6cc7ce52b)
- Bug 1267524 Part 11 - Use member initializer list for nsStyleVisibility. r=heycam (c93d75480e)
- Bug 1267524 Part 12 - Use member initializer list for nsStyleContent. r=heycam (ccc17aa74a)
- Bug 1267524 Part 13 - Use member initializer list for nsStyleTextReset. r=heycam (fc8b6ae837)
- Bug 1267524 Part 14 - Use member initializer list for nsStyleText. r=heycam (d73abb7d32)
- Bug 1267524 Part 15 - Use member initializer list for nsStyleUserInterface. r=heycam (3964558f27)
- Bug 1267524 Part 16 - Use member initializer list for nsStyleUIReset. r=heycam (3154cbc7d2)
- Bug 1267524 Part 17 - Use member initializer list for nsStyleVariables. r=heycam (3d286d2299)
- Bug 1267524 Part 18 - Remove "void" from zero argument functions. r=heycam (57b1a87c19)
- Bug 1267524 Part 19 - Move nsStyleCoord members to initializer list. r=heycam (385231a406)
- Bug 1227327 - Invalidate table parts and MathML frames when background-position changes on them. r=dbaron (088fad2be7)
- Bug 1268290: stylo: Pass SheetParsingMode to Servo, r=bholley (f05d51b7b1)
- Bug 1267833 - Pass the RawServoStyleSet to Servo_GetComputedValuesForAnonymousBox. r=heycam (c4870e2005)
- Bug 1268392 - Make Servo_GetComputedValues take a node rather than an element. r=bholley (61230bdc1f)
- Bug 1268390 - Part 1: Factor out most of nsStyleSet::AddDocStyleSheet for re-use. r=bholley (5bd89657a1)
- Bug 1268390 - Part 2: Add bindings for Servo_InsertStyleSheetBefore. r=bholley (f83ea77d37)
- Bug 1268404 - Part 1: Split out ResolveStyleForText from ResolveStyleForNonElement and pass in the text node. r=bholley (dc40bbc9dc)
- Bug 1268404 - Part 2: Implement ServoStyleSet::ResolveStyleForText. r=bholley (0c6bffbd4b)
- Bug 1268748 - Implement {Resolve,Probe}PseudoElementStyle. r=heycam (cd674703d6)
- Bug 1267560 - Get style structs from ServoComputedValues rather than the rule node, when using the Servo-backed style system. r=bholley (62784ed0ee)
- Bug 1268290 followup: remove stray semicolon on a CLOSED TREE. (609540fab1)
- Bug 1268390 - Part 3: Add support for doc style sheets in ServoStyleSet. r=bholley (787cee0d54)
- Bug 1267564 - Implement a couple of Servo-backed style object methods. r=bholley (b27b0f78a0)
- Bug 1250820 - Part 1: Define scoped enum for CSSPseudoClass::Type. r=heycam (c2992f4c01)
- Bug 1250820 - Part 2: Replace nsCSSPseudoClasses::Type with CSSPseudoClassType. r=heycam (8102ab491b)
- Bug 1250820 - Part 3: Replace notPseudo with negation. r=heycam (94f4b95650)
- Bug 1250820 - Part 4: Add MAX to CSSPseudoClassType. r=heycam (85acf2bc45)
- Bug 1206961 - Use channel->AsyncOpen2() for imageLoader; Remove security checks from callsites (r=bz) (0d5b91ca12)
- Bug 1134163 - Part1.Modify animationstart event timing in order to fire event after end of pending task. r=birtles (e2c333fb8d)
- Bug 1134163 - Part2 - Modify animation tests which rely on animationstart timing. r=birtles (fb780f4298)
- Bug 1067769 - Part 1: Avoid doing RequestRestyle and mutation batch for null target. r=birtles (c3a0c1a1ef)
- Bug 1067769 - Part 2: Support nullable target in KeyframeEffect(ReadOnly) constructor. r=birtles (e8ac02ebf0)
- Bug 1067769 - Part 3: Test for KeyframeEffectReadOnly with null target. r=birtles (9ee7fc48c3)
- Bug 1067769 - Part 4: Add some simple tests for document.getAnimation() in wpt. r=birtles (77c18ad32a)
- Bug 1067769 - Part 5: Support setting KeyframeEffect.target webidl interface. r=smaug (cb450cd6f7)
- Bug 1067769 - Part 6: Rename NonOwningAnimationTarget.h to AnimationTarget.h. r=birtles (45083b4141)
- Bug 1067769 - Part 7: Define OwningAnimationTarget and use it. r=birtles (0a716665aa)
- Bug 1067769 - Part 8: Add ConvertTarget function. r=birtles (2663246043)
- Bug 1067769 - Part 9: Wrap RequestRestyle and UnregisterTarget. r=birtles (1deb75c7e0)
- Bug 1067769 - Part 10: Implement SetTarget(). r=birtles (0823f6da17)
- Bug 1067769 - Part 11: Implement animation mutation observer while setting the target. r=birtles (8224724c49)
- Bug 1067769 - Part 12: Use Maybe<OwningAnimationTarget> in KeyframeEffect(ReadOnly) constructors. r=birtles (e057c15804)
- Bug 1067769 - Part 13: Test for setting the target in basic cases. r=birtles (b6a638a268)
- Bug 1067769 - Part 14: Test for our animation mutation observer. r=birtles (5381522d25)
- Bug 1264067 - [css-grid] 'fr' min-sizing is now invalid. r=dholbert (abc7d63364)
- Bug 550426 - Add support for {background,mask}-position-{x,y}, computed style additions. r=dbaron (0dea650527)
- Bug 1266948 - text-decoration-color: currentcolor should not use value from -webkit-text-fill-color; r=jfkthame (9b36b2f493)
- Bug 1271590 - Rename timespecadd to moz_timespecadd. r=jandem (4b417dabae)
- Bug 550426 - Use background-position-x/y when detecting scroll-linked effects. r=dbaron (478331b348)
- Bug 1227327 - Use regular background drawing for XUL groupbox frames. r=mattwoodrow (db42359656)
- Bug 1260329 - Properly escape the frameTable when running |dmd.py --clamp-contents|. r=mccr8. (b40a5a0f49)
- Bug 1148544 - Update tests to work with new way of handling user agent overrides. r=jchen (2cede65d5b)
- Bug 1262326 - Make test_user_agent_overrides.html work in e10s r=nwgh (81c4d7ba00)
- Bug 1252094 - Export necko-config.h from moz.build; r=ted (0fcb2e3c2b)
- Bug 1180107: Factor out logic for determining whether a flex item's main size could influence cross size. r=mats (94b89305ea)
- Bug 1267471 - Check the snap info when comparing scroll metadata for equality. rs=botond (e5a40f0387)
- Bug 1257288 - Improve the APZ gtest infrastructure to make writing multi-FrameMetrics tests easier. r=kats (b4b898abc2)
- Bug 1256344 - Add a gtest to catch scenarios where the long-press block is interrupted by a non-touch block. r=botond (84982b1ba7)
- Bug 1265510 - Add a gtest for interrupting a scroll snap. r=botond (5f33cdadea)
- Bug 1246290 - Add a simple gtest to exercise the force-disabled-APZ codepaths. r=botond (be91113c70)
- Bug 1267470 - Move more fields from FrameMetrics to ScrollMetadata. r=kats (259f44ab15)
- Bug 1030952 part 4: For flex items with an aspect ratio, stomp on reflow state's main size *and cross size* in final reflow. r=mats (3f02ed9761)
- Bug 550426 - In PropertySupportsVariant, add {background,mask}-position-{x,y} to the list of properties that are parsed by functions. r=dbaron (b350dd9ec4)
- Bug 1258609: Initialize nsICanvasRenderingContextInternal with a DrawTarget instead of a gfxASurface. r=jrmuizel (236656c82d)
- Merge remote-tracking branch 'upstream/dev' into winbuild (c0659b547d)
- [mfbt] NotNull: VC2013 fix (86139057b8)
- layout: put back array initializations back to function body, fix VC2013 build. (3ac23f6474)
2024-09-10 21:28:47 +08:00

1473 lines
46 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 "imgIContainer.h"
#include "imgIRequest.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLImageElement.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 "nsIWinTaskbar.h"
#include "nsISupportsPrimitives.h"
#include "nsIURLFormatter.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "mozilla/WindowsVersion.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 <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 NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
using mozilla::IsWin8OrLater;
using namespace mozilla;
using namespace mozilla::gfx;
NS_IMPL_ISUPPORTS(nsWindowsShellService, nsIWindowsShellService, 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;
}
static bool
GetPrefString(const nsCString& aPrefName, nsAString& aValue)
{
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (!prefs) {
return false;
}
nsAutoCString prefCStr;
nsresult rv = prefs->GetCharPref(aPrefName.get(),
getter_Copies(prefCStr));
if (NS_FAILED(rv)) {
return false;
}
CopyUTF8toUTF16(prefCStr, aValue);
return true;
}
static bool
SetPrefString(const nsCString& aPrefName, const nsString& aValue)
{
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (!prefs) {
return false;
}
nsresult rv = prefs->SetCharPref(aPrefName.get(),
NS_ConvertUTF16toUTF8(aValue).get());
return NS_SUCCEEDED(rv);
}
///////////////////////////////////////////////////////////////////////////////
// Default Browser Registry Settings
//
// The setting of these values are made by an external binary since writing
// these values may require elevation.
//
// - File Extension Mappings
// -----------------------
// The following file extensions:
// .htm .html .shtml .xht .xhtml
// are mapped like so:
//
// HKCU\SOFTWARE\Classes\.<ext>\ (default) REG_SZ PaleMoonHTML
//
// as aliases to the class:
//
// HKCU\SOFTWARE\Classes\PaleMoonHTML\
// DefaultIcon (default) REG_SZ <apppath>,1
// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ <empty string>
//
// - Windows Vista and above Protocol Handler
//
// HKCU\SOFTWARE\Classes\PaleMoonURL\ (default) REG_SZ <appname> URL
// EditFlags REG_DWORD 2
// FriendlyTypeName REG_SZ <appname> URL
// DefaultIcon (default) REG_SZ <apppath>,1
// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ <empty string>
//
// - Protocol Mappings
// -----------------
// The following protocols:
// HTTP, HTTPS, FTP
// are mapped like so:
//
// HKCU\SOFTWARE\Classes\<protocol>\
// DefaultIcon (default) REG_SZ <apppath>,1
// shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
// shell\open\ddeexec (default) REG_SZ <empty string>
//
// - Windows Start Menu (XP SP1 and newer)
// -------------------------------------------------
// The following keys are set to make PaleMoon appear in the Start Menu as the
// browser:
//
// HKCU\SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\
// (default) REG_SZ <appname>
// DefaultIcon (default) REG_SZ <apppath>,0
// InstallInfo HideIconsCommand REG_SZ <uninstpath> /HideShortcuts
// InstallInfo IconsVisible REG_DWORD 1
// InstallInfo ReinstallCommand REG_SZ <uninstpath> /SetAsDefaultAppGlobal
// InstallInfo ShowIconsCommand REG_SZ <uninstpath> /ShowShortcuts
// shell\open\command (default) REG_SZ <apppath>
// shell\properties (default) REG_SZ <appname> &Options
// shell\properties\command (default) REG_SZ <apppath> -preferences
// shell\safemode (default) REG_SZ <appname> &Safe Mode
// shell\safemode\command (default) REG_SZ <apppath> -safe-mode
//
// The values checked are all default values so the value name is not needed.
typedef struct {
const char* keyName;
const char* valueData;
const char* oldValueData;
} SETTING;
#define APP_REG_NAME L"Pale Moon"
#define VAL_FILE_ICON "%APPPATH%,1"
#define VAL_OPEN "\"%APPPATH%\" -osint -url \"%1\""
#define OLD_VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
#define DI "\\DefaultIcon"
#define SOC "\\shell\\open\\command"
#define SOD "\\shell\\open\\ddeexec"
// Used for updating the FTP protocol handler's shell open command under HKCU.
#define FTP_SOC L"Software\\Classes\\ftp\\shell\\open\\command"
#define MAKE_KEY_NAME1(PREFIX, MID) \
PREFIX MID
// The DefaultIcon registry key value should never be used when checking if
// PaleMoon is the default browser for file handlers since other applications
// (e.g. MS Office) may modify the DefaultIcon registry key value to add Icon
// Handlers. see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for
// more info. The FTP protocol is not checked so advanced users can set the FTP
// handler to another application and still have PaleMoon check if it is the
// default HTTP and HTTPS handler.
// *** Do not add additional checks here unless you skip them when aForAllTypes
// is false below***.
static SETTING gSettings[] = {
// File Handler Class
// ***keep this as the first entry because when aForAllTypes is not set below
// it will skip over this check.***
{ MAKE_KEY_NAME1("PaleMoonHTML", SOC), VAL_OPEN, OLD_VAL_OPEN },
// Protocol Handler Class - for Vista and above
{ MAKE_KEY_NAME1("PaleMoonURL", SOC), VAL_OPEN, OLD_VAL_OPEN },
// Protocol Handlers
{ MAKE_KEY_NAME1("HTTP", DI), VAL_FILE_ICON },
{ MAKE_KEY_NAME1("HTTP", SOC), VAL_OPEN, OLD_VAL_OPEN },
{ MAKE_KEY_NAME1("HTTPS", DI), VAL_FILE_ICON },
{ MAKE_KEY_NAME1("HTTPS", SOC), VAL_OPEN, OLD_VAL_OPEN }
};
// The settings to disable DDE are separate from the default browser settings
// since they are only checked when PaleMoon is the default browser and if they
// are incorrect they are fixed without notifying the user.
static SETTING gDDESettings[] = {
// File Handler Class
{ MAKE_KEY_NAME1("Software\\Classes\\PaleMoonHTML", SOD) },
// Protocol Handler Class - for Vista and above
{ MAKE_KEY_NAME1("Software\\Classes\\PaleMoonURL", SOD) },
// Protocol Handlers
{ MAKE_KEY_NAME1("Software\\Classes\\FTP", SOD) },
{ MAKE_KEY_NAME1("Software\\Classes\\HTTP", SOD) },
{ MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) }
};
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;
}
NS_IMETHODIMP
nsWindowsShellService::ShortcutMaintenance()
{
nsresult rv;
// XXX App ids were updated to a constant install path hash,
// XXX this code can be removed after a few upgrade cycles.
// Launch helper.exe so it can update the application user model ids on
// shortcuts in the user's taskbar and start menu. This keeps older pinned
// shortcuts grouped correctly after major updates. Note, we also do this
// through the upgrade installer script, however, this is the only place we
// have a chance to trap links created by users who do control the install/
// update process of the browser.
nsCOMPtr<nsIWinTaskbar> taskbarInfo =
do_GetService(NS_TASKBAR_CONTRACTID);
if (!taskbarInfo) // If we haven't built with win7 sdk features, this fails.
return NS_OK;
// Avoid if this isn't Win7+
bool isSupported = false;
taskbarInfo->GetAvailable(&isSupported);
if (!isSupported)
return NS_OK;
nsAutoString appId;
if (NS_FAILED(taskbarInfo->GetDefaultGroupId(appId)))
return NS_ERROR_UNEXPECTED;
NS_NAMED_LITERAL_CSTRING(prefName, "browser.taskbar.lastgroupid");
nsCOMPtr<nsIPrefBranch> prefs =
do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!prefs)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsISupportsString> prefString;
rv = prefs->GetComplexValue(prefName.get(),
NS_GET_IID(nsISupportsString),
getter_AddRefs(prefString));
if (NS_SUCCEEDED(rv)) {
nsAutoString version;
prefString->GetData(version);
if (!version.IsEmpty() && version.Equals(appId)) {
// We're all good, get out of here.
return NS_OK;
}
}
// Update the version in prefs
prefString =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
prefString->SetData(appId);
rv = prefs->SetComplexValue(prefName.get(),
NS_GET_IID(nsISupportsString),
prefString);
if (NS_FAILED(rv)) {
NS_WARNING("Couldn't set last user model id!");
return NS_ERROR_UNEXPECTED;
}
nsAutoString appHelperPath;
if (NS_FAILED(GetHelperPath(appHelperPath)))
return NS_ERROR_UNEXPECTED;
appHelperPath.AppendLiteral(" /UpdateShortcutAppUserModelIds");
return LaunchHelper(appHelperPath);
}
static bool
IsAARDefault(const RefPtr<IApplicationAssociationRegistration>& pAAR,
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"ArcticFoxURL" : L"ArcticFoxHTML";
bool isDefault = !wcsicmp(registeredApp, progID);
CoTaskMemFree(registeredApp);
return isDefault;
}
static void
GetUserChoiceKeyName(LPCWSTR aClassName, bool aIsProtocol,
nsAString& aKeyName)
{
aKeyName.AssignLiteral(aIsProtocol
? "Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\"
: "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\");
aKeyName.Append(aClassName);
aKeyName.AppendLiteral("\\UserChoice");
}
static void
GetHashPrefName(LPCWSTR aClassName, nsACString& aPrefName)
{
aPrefName.AssignLiteral("browser.shell.associationHash.");
aPrefName.Append(NS_ConvertUTF16toUTF8(*aClassName == L'.' ? aClassName + 1
: aClassName));
}
static bool
SaveWin8RegistryHash(const RefPtr<IApplicationAssociationRegistration>& pAAR,
LPCWSTR aClassName)
{
bool isProtocol = *aClassName != L'.';
bool isDefault = IsAARDefault(pAAR, aClassName);
// We can save the value only if ArctiFox is the default.
if (!isDefault) {
return isDefault;
}
nsAutoString keyName;
GetUserChoiceKeyName(aClassName, isProtocol, keyName);
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1");
if (!regKey) {
return isDefault;
}
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
keyName, nsIWindowsRegKey::ACCESS_READ);
if (NS_FAILED(rv)) {
return isDefault;
}
nsAutoString hash;
rv = regKey->ReadStringValue(NS_LITERAL_STRING("Hash"), hash);
if (NS_FAILED(rv)) {
return isDefault;
}
nsAutoCString prefName;
GetHashPrefName(aClassName, prefName);
SetPrefString(prefName, hash);
return isDefault;
}
static bool
RestoreWin8RegistryHash(const RefPtr<IApplicationAssociationRegistration>& pAAR,
LPCWSTR aClassName)
{
nsAutoCString prefName;
GetHashPrefName(aClassName, prefName);
nsAutoString hash;
if (!GetPrefString(prefName, hash)) {
return false;
}
bool isProtocol = *aClassName != L'.';
nsString progId = isProtocol ? NS_LITERAL_STRING("ArcticFoxURL")
: NS_LITERAL_STRING("ArcticFoxHTML");
nsAutoString keyName;
GetUserChoiceKeyName(aClassName, isProtocol, keyName);
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1");
if (!regKey) {
return false;
}
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
keyName, nsIWindowsRegKey::ACCESS_READ);
if (NS_SUCCEEDED(rv)) {
nsAutoString currValue;
if (NS_SUCCEEDED(regKey->ReadStringValue(NS_LITERAL_STRING("Hash"),
currValue)) &&
currValue.Equals(hash) &&
NS_SUCCEEDED(regKey->ReadStringValue(NS_LITERAL_STRING("ProgId"),
currValue)) &&
currValue.Equals(progId)) {
// The value is already set.
return true;
}
// We need to close this explicitly because nsIWindowsRegKey::SetKey
// does not close the old key.
regKey->Close();
}
// We have to use the registry function directly because
// nsIWindowsRegKey::Create will only return NS_ERROR_FAILURE
// on failure.
HKEY theKey;
DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0,
KEY_READ | KEY_SET_VALUE, &theKey);
if (REG_FAILED(res)) {
if (res != ERROR_ACCESS_DENIED && res != ERROR_FILE_NOT_FOUND) {
return false;
}
if (res == ERROR_ACCESS_DENIED) {
res = ::RegDeleteKeyW(HKEY_CURRENT_USER, keyName.get());
if (REG_FAILED(res)) {
return false;
}
}
res = ::RegCreateKeyExW(HKEY_CURRENT_USER, keyName.get(), 0,
nullptr, 0, KEY_READ | KEY_SET_VALUE,
nullptr, &theKey, nullptr);
if (REG_FAILED(res)) {
return false;
}
}
regKey->SetKey(theKey);
rv = regKey->WriteStringValue(NS_LITERAL_STRING("Hash"), hash);
if (NS_FAILED(rv)) {
return false;
}
rv = regKey->WriteStringValue(NS_LITERAL_STRING("ProgId"), progId);
if (NS_FAILED(rv)) {
return false;
}
return IsAARDefault(pAAR, aClassName);
}
static void
SaveWin8RegistryHashes(bool aCheckAllTypes, bool* aIsDefaultBrowser)
{
RefPtr<IApplicationAssociationRegistration> pAAR;
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
nullptr,
CLSCTX_INPROC,
IID_IApplicationAssociationRegistration,
getter_AddRefs(pAAR));
if (FAILED(hr)) {
return;
}
bool res = SaveWin8RegistryHash(pAAR, L"http");
if (*aIsDefaultBrowser) {
*aIsDefaultBrowser = res;
}
SaveWin8RegistryHash(pAAR, L"https");
SaveWin8RegistryHash(pAAR, L"ftp");
res = SaveWin8RegistryHash(pAAR, L".html");
if (*aIsDefaultBrowser && aCheckAllTypes) {
*aIsDefaultBrowser = res;
}
SaveWin8RegistryHash(pAAR, L".htm");
SaveWin8RegistryHash(pAAR, L".shtml");
SaveWin8RegistryHash(pAAR, L".xhtml");
SaveWin8RegistryHash(pAAR, L".xht");
}
static bool
RestoreWin8RegistryHashes(bool aClaimAllTypes)
{
RefPtr<IApplicationAssociationRegistration> pAAR;
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
nullptr,
CLSCTX_INPROC,
IID_IApplicationAssociationRegistration,
getter_AddRefs(pAAR));
if (FAILED(hr)) {
return false;
}
bool res = RestoreWin8RegistryHash(pAAR, L"http");
res = RestoreWin8RegistryHash(pAAR, L"https") && res;
RestoreWin8RegistryHash(pAAR, L"ftp");
bool res2 = RestoreWin8RegistryHash(pAAR, L".html");
res2 = RestoreWin8RegistryHash(pAAR, L".htm") && res2;
if (aClaimAllTypes) {
res = res && res2;
}
RestoreWin8RegistryHash(pAAR, L".shtml");
RestoreWin8RegistryHash(pAAR, L".xhtml");
RestoreWin8RegistryHash(pAAR, L".xht");
return res;
}
/*
* Query's the AAR for the default status.
* This only checks for PaleMoonURL and if aCheckAllTypes is set, then
* it also checks for PaleMoonHTML. Note that those ProgIDs are shared
* by all PaleMoon browsers.
*/
bool
nsWindowsShellService::IsDefaultBrowserVista(bool aCheckAllTypes,
bool* aIsDefaultBrowser)
{
RefPtr<IApplicationAssociationRegistration> pAAR;
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
nullptr,
CLSCTX_INPROC,
IID_IApplicationAssociationRegistration,
getter_AddRefs(pAAR));
if (FAILED(hr)) {
return false;
}
if (aCheckAllTypes) {
BOOL res;
hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE,
APP_REG_NAME,
&res);
*aIsDefaultBrowser = res;
} else if (!IsWin8OrLater()) {
*aIsDefaultBrowser = IsAARDefault(pAAR, L"http");
}
return true;
}
NS_IMETHODIMP
nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
bool aForAllTypes,
bool* aIsDefaultBrowser)
{
// Assume we're the default unless one of the several checks below tell us
// otherwise.
*aIsDefaultBrowser = true;
wchar_t exePath[MAX_BUF];
if (!::GetModuleFileNameW(0, exePath, MAX_BUF))
return NS_ERROR_FAILURE;
// Convert the path to a long path since GetModuleFileNameW returns the path
// that was used to launch PaleMoon which is not necessarily a long path.
if (!::GetLongPathNameW(exePath, exePath, MAX_BUF))
return NS_ERROR_FAILURE;
nsAutoString appLongPath(exePath);
HKEY theKey;
DWORD res;
nsresult rv;
wchar_t currValue[MAX_BUF];
SETTING* settings = gSettings;
if (!aForAllTypes && IsWin8OrLater()) {
// Skip over the file handler check
settings++;
}
SETTING* end = gSettings + sizeof(gSettings) / sizeof(SETTING);
for (; settings < end; ++settings) {
NS_ConvertUTF8toUTF16 keyName(settings->keyName);
NS_ConvertUTF8toUTF16 valueData(settings->valueData);
int32_t offset = valueData.Find("%APPPATH%");
valueData.Replace(offset, 9, appLongPath);
rv = OpenKeyForReading(HKEY_CLASSES_ROOT, keyName, &theKey);
if (NS_FAILED(rv)) {
*aIsDefaultBrowser = false;
return NS_OK;
}
::ZeroMemory(currValue, sizeof(currValue));
DWORD len = sizeof currValue;
res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr,
(LPBYTE)currValue, &len);
// Close the key that was opened.
::RegCloseKey(theKey);
if (REG_FAILED(res) ||
_wcsicmp(valueData.get(), currValue)) {
// Key wasn't set or was set to something other than our registry entry.
NS_ConvertUTF8toUTF16 oldValueData(settings->oldValueData);
offset = oldValueData.Find("%APPPATH%");
oldValueData.Replace(offset, 9, appLongPath);
// The current registry value doesn't match the current or the old format.
if (_wcsicmp(oldValueData.get(), currValue)) {
*aIsDefaultBrowser = false;
return NS_OK;
}
res = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, PromiseFlatString(keyName).get(),
0, KEY_SET_VALUE, &theKey);
if (REG_FAILED(res)) {
// If updating the open command fails try to update it using the helper
// application when setting PaleMoon as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
const nsString &flatValue = PromiseFlatString(valueData);
res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
(const BYTE *) flatValue.get(),
(flatValue.Length() + 1) * sizeof(char16_t));
// Close the key that was created.
::RegCloseKey(theKey);
if (REG_FAILED(res)) {
// If updating the open command fails try to update it using the helper
// application when setting PaleMoon as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
}
}
// Only check if PaleMoon is the default browser on Vista and above if the
// previous checks show that PaleMoon is the default browser.
if (*aIsDefaultBrowser) {
if (IsWin8OrLater()) {
SaveWin8RegistryHashes(aForAllTypes, aIsDefaultBrowser);
}
}
// To handle the case where DDE isn't disabled due for a user because there
// account didn't perform a PaleMoon update this will check if PaleMoon is the
// default browser and if dde is disabled for each handler
// and if it isn't disable it. When PaleMoon is not the default browser the
// helper application will disable dde for each handler.
if (*aIsDefaultBrowser && aForAllTypes) {
// Check ftp settings
end = gDDESettings + sizeof(gDDESettings) / sizeof(SETTING);
for (settings = gDDESettings; settings < end; ++settings) {
NS_ConvertUTF8toUTF16 keyName(settings->keyName);
rv = OpenKeyForReading(HKEY_CURRENT_USER, keyName, &theKey);
if (NS_FAILED(rv)) {
::RegCloseKey(theKey);
// If disabling DDE fails try to disable it using the helper
// application when setting PaleMoon as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
::ZeroMemory(currValue, sizeof(currValue));
DWORD len = sizeof currValue;
res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr,
(LPBYTE)currValue, &len);
// Close the key that was opened.
::RegCloseKey(theKey);
if (REG_FAILED(res) || char16_t('\0') != *currValue) {
// Key wasn't set or was set to something other than our registry entry.
// Delete the key along with all of its childrean and then recreate it.
const nsString &flatName = PromiseFlatString(keyName);
::SHDeleteKeyW(HKEY_CURRENT_USER, flatName.get());
res = ::RegCreateKeyExW(HKEY_CURRENT_USER, flatName.get(), 0, nullptr,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
nullptr, &theKey, nullptr);
if (REG_FAILED(res)) {
// If disabling DDE fails try to disable it using the helper
// application when setting PaleMoon as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, (const BYTE *) L"",
sizeof(char16_t));
// Close the key that was created.
::RegCloseKey(theKey);
if (REG_FAILED(res)) {
// If disabling DDE fails try to disable it using the helper
// application when setting PaleMoon as the default browser.
*aIsDefaultBrowser = false;
return NS_OK;
}
}
}
// Update the FTP protocol handler's shell open command if it is the old
// format.
res = ::RegOpenKeyExW(HKEY_CURRENT_USER, FTP_SOC, 0, KEY_ALL_ACCESS,
&theKey);
// Don't update the FTP protocol handler's shell open command when opening
// its registry key fails under HKCU since it most likely doesn't exist.
if (NS_FAILED(rv)) {
return NS_OK;
}
NS_ConvertUTF8toUTF16 oldValueOpen(OLD_VAL_OPEN);
int32_t offset = oldValueOpen.Find("%APPPATH%");
oldValueOpen.Replace(offset, 9, appLongPath);
::ZeroMemory(currValue, sizeof(currValue));
DWORD len = sizeof currValue;
res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr, (LPBYTE)currValue,
&len);
// Don't update the FTP protocol handler's shell open command when the
// current registry value doesn't exist or matches the old format.
if (REG_FAILED(res) ||
_wcsicmp(oldValueOpen.get(), currValue)) {
::RegCloseKey(theKey);
return NS_OK;
}
NS_ConvertUTF8toUTF16 valueData(VAL_OPEN);
valueData.Replace(offset, 9, appLongPath);
const nsString &flatValue = PromiseFlatString(valueData);
res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
(const BYTE *) flatValue.get(),
(flatValue.Length() + 1) * sizeof(char16_t));
// Close the key that was created.
::RegCloseKey(theKey);
// If updating the FTP protocol handlers shell open command fails try to
// update it using the helper application when setting PaleMoon as the
// default browser.
if (REG_FAILED(res)) {
*aIsDefaultBrowser = false;
}
}
return NS_OK;
}
static nsresult
DynSHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo)
{
// shell32.dll is in the knownDLLs list so will always be loaded from the
// system32 directory.
static const wchar_t kSehllLibraryName[] = L"shell32.dll";
HMODULE shellDLL = ::LoadLibraryW(kSehllLibraryName);
if (!shellDLL) {
return NS_ERROR_FAILURE;
}
decltype(SHOpenWithDialog)* SHOpenWithDialogFn =
(decltype(SHOpenWithDialog)*) GetProcAddress(shellDLL, "SHOpenWithDialog");
if (!SHOpenWithDialogFn) {
return NS_ERROR_FAILURE;
}
nsresult rv =
SUCCEEDED(SHOpenWithDialogFn(hwndParent, poainfo)) ? NS_OK :
NS_ERROR_FAILURE;
FreeLibrary(shellDLL);
return rv;
}
nsresult
nsWindowsShellService::LaunchControlPanelDefaultsSelectionUI()
{
IApplicationAssociationRegistrationUI* pAARUI;
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI,
NULL,
CLSCTX_INPROC,
IID_IApplicationAssociationRegistrationUI,
(void**)&pAARUI);
if (SUCCEEDED(hr)) {
hr = pAARUI->LaunchAdvancedAssociationUI(APP_REG_NAME);
pAARUI->Release();
}
return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
}
nsresult
nsWindowsShellService::LaunchControlPanelDefaultPrograms()
{
// Default Programs is a Vista+ feature
if (!IsVistaOrLater()) {
return NS_ERROR_FAILURE;
}
// 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;
}
WCHAR params[] = L"control.exe /name Microsoft.DefaultPrograms /page pageDefaultProgram";
STARTUPINFOW si = {sizeof(si), 0};
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWDEFAULT;
PROCESS_INFORMATION pi = {0};
if (!CreateProcessW(controlEXEPath, params, 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 (!IsWindowsLogonConnected() && SettingsAppBelievesConnected()) {
// Use the classic Control Panel to work around a bug 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);
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;
return DynSHOpenWithDialog(nullptr, &info);
}
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() &&
!RestoreWin8RegistryHashes(aClaimAllTypes)) {
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();
}
bool isDefault;
SaveWin8RegistryHashes(aClaimAllTypes, &isDefault);
}
}
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;
}
static nsresult
WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
{
nsresult rv;
RefPtr<SourceSurface> surface =
aImage->GetFrame(imgIContainer::FRAME_FIRST,
imgIContainer::FLAG_SYNC_DECODE);
NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
// For either of the following formats we want to set the biBitCount member
// of the BITMAPINFOHEADER struct to 32, below. For that value the bitmap
// format defines that the A8/X8 WORDs in the bitmap byte stream be ignored
// for the BI_RGB value we use for the biCompression member.
MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
surface->GetFormat() == SurfaceFormat::B8G8R8X8);
RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
int32_t width = dataSurface->GetSize().width;
int32_t height = dataSurface->GetSize().height;
int32_t bytesPerPixel = 4 * sizeof(uint8_t);
uint32_t bytesPerRow = bytesPerPixel * width;
// initialize these bitmap structs which we will later
// serialize directly to the head of the bitmap file
BITMAPINFOHEADER bmi;
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biWidth = width;
bmi.biHeight = height;
bmi.biPlanes = 1;
bmi.biBitCount = (WORD)bytesPerPixel*8;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = bytesPerRow * height;
bmi.biXPelsPerMeter = 0;
bmi.biYPelsPerMeter = 0;
bmi.biClrUsed = 0;
bmi.biClrImportant = 0;
BITMAPFILEHEADER bf;
bf.bfType = 0x4D42; // 'BM'
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bf.bfSize = bf.bfOffBits + bmi.biSizeImage;
// get a file output stream
nsCOMPtr<nsIOutputStream> stream;
rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
NS_ENSURE_SUCCESS(rv, rv);
DataSourceSurface::MappedSurface map;
if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
return NS_ERROR_FAILURE;
}
// write the bitmap headers and rgb pixel data to the file
rv = NS_ERROR_FAILURE;
if (stream) {
uint32_t written;
stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
if (written == sizeof(BITMAPFILEHEADER)) {
stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written);
if (written == sizeof(BITMAPINFOHEADER)) {
// write out the image data backwards because the desktop won't
// show bitmaps with negative heights for top-to-bottom
uint32_t i = map.mStride * height;
do {
i -= map.mStride;
stream->Write(((const char*)map.mData) + i, bytesPerRow, &written);
if (written == bytesPerRow) {
rv = NS_OK;
} else {
rv = NS_ERROR_FAILURE;
break;
}
} while (i != 0);
}
}
stream->Close();
}
dataSurface->Unmap();
return rv;
}
NS_IMETHODIMP
nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement,
int32_t aPosition)
{
nsresult rv;
nsCOMPtr<imgIContainer> container;
nsCOMPtr<nsIDOMHTMLImageElement> imgElement(do_QueryInterface(aElement));
if (!imgElement) {
// XXX write background loading stuff!
return NS_ERROR_NOT_AVAILABLE;
}
else {
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;
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"
nsString fileLeafName;
rv = shellBundle->GetStringFromName
(MOZ_UTF16("desktopBackgroundLeafNameWin"),
getter_Copies(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\PaleMoon\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 = 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.AssignLiteral("0");
tile.AssignLiteral("1");
break;
case BACKGROUND_CENTER:
style.AssignLiteral("0");
tile.AssignLiteral("0");
break;
case BACKGROUND_STRETCH:
style.AssignLiteral("2");
tile.AssignLiteral("0");
break;
case BACKGROUND_FILL:
style.AssignLiteral("10");
tile.AssignLiteral("0");
break;
case BACKGROUND_FIT:
style.AssignLiteral("6");
tile.AssignLiteral("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.AppendLiteral("\\");
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);
}
NS_IMETHODIMP
nsWindowsShellService::GetDefaultFeedReader(nsIFile** _retval)
{
*_retval = nullptr;
nsresult rv;
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
NS_LITERAL_STRING("feed\\shell\\open\\command"),
nsIWindowsRegKey::ACCESS_READ);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString path;
rv = regKey->ReadStringValue(EmptyString(), path);
NS_ENSURE_SUCCESS(rv, rv);
if (path.IsEmpty())
return NS_ERROR_FAILURE;
if (path.First() == '"') {
// Everything inside the quotes
path = Substring(path, 1, path.FindChar('"', 1) - 1);
}
else {
// Everything up to the first space
path = Substring(path, 0, path.FindChar(' '));
}
nsCOMPtr<nsIFile> defaultReader =
do_CreateInstance("@mozilla.org/file/local;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = defaultReader->InitWithPath(path);
NS_ENSURE_SUCCESS(rv, rv);
bool exists;
rv = defaultReader->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (!exists)
return NS_ERROR_FAILURE;
NS_ADDREF(*_retval = defaultReader);
return NS_OK;
}