mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
bfe2ea5afa
- reapply Bug 1574573 - Disambiguate a use of Handle in XPCShellEnvironment.cpp r=Ehsan (a674c4b006) - re-create --disable-applemedia option (needed for pre-10.7 Mac) in new configure ssytem (28e2fd5fee) - Bug 1255707 - Part 2. Remove ScreenSizeChanged. r=snorp (3a93e4e768) - Bug 1250418 - Remove the assertion check of mCanSend in CompositorCh ld::ActorDestroy, r=nical (14bb402a1d) - Bug 1250718 - Improve layer logging for preserve-3d layers. r=thinker (f373a50040) - Bug 1232042 - Addendum: Add comment for mLayerManager check. r=jrmuizel (2b69aa784a) - Bug 1239861. Skip composite if vsync time is before force composite time. r=kats (5ee4038157) - Bug 1241678 - Fix low-volume null-deref crash. r=BenWa (b28d944615) - Rename PCompositor to PCompositorBridge. (bug 1258479 part 2, r=mattwoodrow) (dd535a9bdd) - Bug 1238160 - Set frame type on TabContext. r=billm,mayhemer (54424d792b) - bits of 1240471 (fb34a97806) - Bug 1238160 - Test mozbrowser APIs to ensure no content exposure. r=bz (17a0ac611c) - Bug 1238160 - Enable mozbrowser frames on desktop. r=bz (5b42b5403d) - Bug 1197461 - Implement Permissions.revoke. r=poiru,baku (306712f9ca) - Bug 1197461 - e10s support for Permissions.revoke. r=poiru (bbda5df25d) - Bug 1220184 - Eliminate Gingerbread compatibility. r=froydnj, r=nalexander (dce9e4f9e8) - Bug 1238160 - Set docshell isolation mode. r=smaug (6ac2c21d1d) - fix of Bug 1238160 (786a554a6a) - Bug 1237364 - nsFrameLoader.cpp can set the userContextId directly using nsIDocShell, r=smaug (fea166caa3) - Bug 1227861 - Add OriginAttributes getter/setter into nsIDocShell. r=smaug, sicking (4f8ac4f8ce) - Bug 1246956 - Add originURI to Sessionstore. r=bz,Yoric,mfinkle (a1dcd44194) - Bug 1246956 - Add loadReplace to session history. r=yoric r=mfinkle (662e66ad7e) - Bug 1252811 - remove mIsInIsolatedMozBrowser from nsDocShell. r=smaug (b5927775b7) - Bug 1250917 - Remove NS_SUCCESS_I_DID_SOMETHING; r=bholley (9dd6fe351b) - Bug 1225053 - use null principal in gfxSVGGlyphs.cpp r=edwin (597d10fd4e) - Bug 1226120 - add test for unknownContentType.xul and file types with a default handler but always ask set, r=mconley (dd95e18fd9) - Bug 1254118 - Web protocol handlers need more testing coverage, r=felipe. (4fb6949d10) - Bug 1253307 - Use a better function to load web handler apps in e10s. r=billm/mconley (28695be154) - Bug 1155241: Check mInstanceOwner for nullptr in nsObjectLoadingContent::PluginDestroyed; r=smaug (ad60991e3e) - Bug 1229220 - Update the scrollbar visibility prefs when initializing a TabChild; r=smaug (28997e0a6d) - Bug 1252262 - Don't combine the client offset into the outer rect for the child process. r=jimm (f415c0418e) - Bug 1249943 - Make test_basic_pan work on Fennec and Linux as well. r=botond (657c940be1) - bit of bug 1245765 part 5 (82463f7eaa) - Bug 1207512 - Remove the JS_IsRunning call in nsObjectLoadingContent::ScriptRequestPluginInstance; r=bholley (76047284a6) - minor cleanup and Telemetry pieces (2765a1408d) - Bug 1239463 - Do not assert when notifying an inactive document about changed content from the plugin crash notification. r=bz (03bf38a683) - Bug 1192450 - Remove PlayPreview registration from Shumway. r=jet (9b6e131876) - Bug 1200602 - Use the alternate content for <applet>. r=kmachulis (843fccf0aa) - Bug 1236900 - Remove useless null check since mOwnerContent cannot be null. r=jst (a7e2d4b95c) - bug 1257287 - add nsIDocShell::GetEdItingSession() (abd9022426) - bug 1257287 - add nsIDocShell.tabChild r=smaug (6fe910c2b8) - Bug 1256626: P1. Add NotifyBenchmarkResult ipc methods. r=jimm (02ab9cb0f6) - Bug 1256626: P2. Use NotifyBenchmarkResult to save VP9 result. r=jimm (877277768c) - Bug 1256626. Workaround Microsoft macro silliness. r=me (070e5a8cf0) - Bug 1183915 - Put images dragged from content processes in the drag data in the parent. r=smaug (72906fab07) - Bug 1228652 - Check for window.closed after flushing messages in navigateAndRestore. r=mossop (fd9d2b7d42) - Bug 1217517 - nullcheck consumers for gKeywordURIFixup, r=jaws (adf6388856) - Bug 951695 - Rename 'Character Encoding' to 'Text Encoding'. r=jaws (046e9644c2) - Bug 1088710 - part 2: make it work on e10s, r=mconley (479366cba8) - Bug 1147720 - Fix intermittent waitForDocLoadAndStopIt() timeouts by keeping a strong reference to the progress listener r=mak (4e9fa3f8c2) - Bug 1228754, r=mak,bz (a33bc4da9c) - Bug 1250482 - r=mak (0f69dd5f69) - Bug 798249 - track when we're 'inside' a loadURI call when dealing with Stop() calls resulting from the same, r=mconley (e06b5b44e9) - Bug 1254657 - change how we send Content:LoadURIResult to avoid upsetting RemoteWebProgress.jsm, r=mconley (915e7a1be6) - 1253584 - Fix and enable browser_NetworkPrioritizer.js for e10s. r=mconley (9757c53ab6) - Bug 1254522 - Make remote-browser.xml and browser.xml not depend on Firefox's browser.js. r=mconley (0a15acf7cc) - Bug 621158 - make appcache use messaging for quota management, r=mayhemer,jaws (7e69707327) - Bug 1255511 - Skip beforeunload prompts once nsIAppStartup shuttingDown returns true. r=Gijs (66bb2ce055) - Bug 884355 - Warn about closing multiple tabs when "Never remember history" is enabled" r=gavin (7e61149b88) - Bug 1228754 - bustage followup, rs=me,bustage Bug 1228754 - correct comments from bustage fix, rs=me, DONTBUILD (ef4d053a24) - Bug 985777 - add a whitelist for URLs that we can switch to/from private browsing windows, r=ehsan (dc799a2213) - Bug 963945 - Add about:addons URI as whitelisted so that it can be refocused instead of opening duplicate tabs in private browsing. r=jdm (8d5770a31c) - reshuffle misspatch (8d2f7c2924) - Bug 1236126 - fix oversight in principal handling for dialogs with host-less principals, r=aryx (1827672cae) - align some stuff (256ffe50fa) - Bug 1252239: Trap errors thrown by speculativeConnect. r=ttaubert (726d890a7b) - Bug 1093153: enabled and re-factored browser_aboutHome.js to work correctly in e10s mode. r=mak (90518a9742) - Bug 1239671 - Don't let session store override persistent cookies, r=ehsan (ee5b04fc97) - Bug 1255685 - SessionStorage.jsm should use origin attributes from docshell. r=sicking (1f055f6ab2) - Bug 1234021 - Catch exceptions raised by storage.length in SessionStorage.jsm, r=mconley (85ed6cf819) - Bug 1192394 - Force an image load whenever the thumbnail file changes. r=adw (c194d868f9) - let-var (f5e9a53170) - Bug 529899 - Purge cookies on clean shutdown with "Keep cookies until I close Firefox" r=Yoric (1a15abd5f3) - Bug 1071104 - Remove legacy "hasWrittenState" flag from SessionWorker r=yoric (484e1ac5b1) - Bug 1198898 - Determining number of tabs/windows restored by Session Restore;r=mconley (5bda3ecc88) - Bug 1245891 - Changing Session Restore Talos tests to include the time to restore actual tabs;r=mconley (d7c5957192) - Bug 1210940 - New Browser Component: Newtab r=Mardak (a59fd6c88e) - Bug 1219454 - Replace 'show' with 'receive' in about:permissions and control center for consistent messaging around notifications and to account for new Push permission. r=MattN (60cc4211ec) - align (b7bc52abef) - Bug 868711 - Remove confusing expression in _trackSlowStartup. r=gavin (b2d5609496) - Bug 1231112 - work around tab groups migration issue in safe mode, r=ttaubert (e71ceebd3f) - Bug 1249608 - Don't run UI migration steps with new profiles. r=gijs (b6f92e45ba) - Bug 910431 - Electrolysis: Permission code followup. f=felipe (1bf556eeea) - align some e10s (05aa76a560) - Bug 1250109 - Change DOMEventTargetHelper subclasses to not assume that GetOwner() is non-null, since it can be nulled out by navigation. r=bzbarsky (deb440c2a4) - Bug 908277 - Prevent permission UI errors when PopupNotifications is not available. r=dolske (dcefc44921) - Bug 1199805 - Fix displayURI typo on site permission prompts. r=bgrins (78dbd44c98) - Bug 1246028 Implement chrome.commands.getAll. r=kmag (b263fbe137) - Bug 1242557 - Import missing commands API schema file. r=kmag (b930a95b2f) - Bug 1249689 - replace bootstrapScope with an activeAddons Map() that contains it r=mossop (00bef48286) - Bug 1249689 - generate and provide a Symbol for each add-on on startup r=mossop (bd7b936bcb) - Bug 685155: Treat symbolic links the same as proxy files in the Add-on Manager. r=Mossop (4f458140df) - Bug 1244248: Test that the certificate database is cached. r=rhelmer (a5cc6e8d75) - Bug 1250784: Part 1 - [webext] Add support for options_ui via inline browsers in the Add-on Manager. r=Mossop (62b6efe654) - Bug 1250784: Part 2 - [webext] Fix some issues that cause noisy tests. r=Mossop (4ada262435) - Bug 1252250 - Implement browser.bookmarks.removeTree(), r=kmag r=mak (7e67b5ccf1) - Bug 1253652 - Fix browser.bookmarks.move() and add tests for it. r=kmag, r=mak (151a8bf09a) - Bug 1250784: Follow-up: Fix merge conflict in bookmarks API. r=me (3db6ea04ea) - Bug 1251269 - Implement browser.bookmarks.getRecent(), r=kmag r=mak (d4564d6aee) - Bug 1246614 - Check if system add-ons directory exists before trying to clean it. r=mossop (c2d59f34a8) - Bug 1041514 - Don't show default browser prompt if a user opts out in the installer. r=jimm (b2ccf151f7) - use ArcticFoxHTML and ArcticFoxURL keys, not to mix with Firefox (e6d36fdd78) - Bug 1207784 - skip permission hooks in createOffer when called from hiddenWindow (add-ons). r=mt (b90a4c940f) - Bug 1209766 - Update validation message before showing notification. r=khuey (8c9a865969) - Bug 1206560 - Show the site favicon in XUL notifications. r=jaws (e5bad6ea20) - Bug 1248497 창 Add promise support to the sendMessage APIs. r=billm (e26a805c92) - Bug 911216 - Part 1: Add tests directly testing content Promise constructor resolved with chrome Promise. r=bz (1b2f1ec6b8) - Bug 911216 - Part 2: Add self-hosting intrinsic for calling wrapped functions without wrapper security checks. r=efaust,bholley (de086e8422) - Bug 911216 - Part 3: Allow wrapped self-hosted functions and intrinsics in the callFunction debug check. r=efaust (c02e6337fe) - Bug 1251921 - Do not call debugger hooks with half-initialized frame if InterpeterFrame::prologue fails. (r=jorendorff) (9873720345) - Bug 1256342. Fix typed array iteration to work correctly over Xrays. r=till (6a7f5c12c6) - Bug 1256376. Fix forEach on typed arrays to work over Xrays from web extension sandboxes. r=till (ab19703ab5) - Bug 1253436 - Add __repr__ to BaseLibrary and BaseProgram; r=glandium (a04a16f2ac) - Bug 1238064 - Update docs to reflect new workflow. r=mossop (c7670ac086) - Bug 911216 - Part 4: Add self-hosting intrinsic for creating arrays in other compartments. r=efaust (37b14521fb) - Bug 1233497 - Temporarily allow unsafe CPOWs in Promise-backend.js and Task.jsm. r=billm (d2672a456a) - Bug 1225041 - Implement ES6 Annex B.3.5 for direct eval. (r=jorendorff) (daf24f0e34) - Bug 1254185 - Deal with missing arguments assigned to block bindings. (r=jimb) (3ce53dcd06) - Bug 1250506 - check if node is acceptable as a child before creating an accessible for it, r=davidb (5960ba726d) - Bug 1251941 - aria::GetRoleMap should take element, r=davidb (e9ee4e20ea) - Bug 1251944 - get rid of nsCoreUtils::GetRoleContent, r=davidb (a2bf199bb4) - Bug 1257030 - Add support for supplying preexisting stack instead of capturing one for use as the async parent stack of CallbackObject. r=bz,tromey (a4ddb41fac) - Bug 1232291 - Non-used header in MessagePortService.*, r=smaug (1e2398e314) - Bug 1255655 - Const-ify sWAIRoleMaps. r=tbsaunde. (09653e44af) - align (24667f7952) - Bug 1253438 - Expose Push observer notification topics. r=markh (b62a068d4b)
1383 lines
44 KiB
C++
1383 lines
44 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>
|
|
|
|
#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,
|
|
®isteredApp);
|
|
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::LaunchModernSettingsDialogDefaultApps()
|
|
{
|
|
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;
|
|
}
|