gecko/xpfe/components/winhooks/nsWindowsHooks.cpp

989 lines
37 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bill Law <law@netscape.com>
* Syd Logan <syd@netscape.com> added turbo mode stuff
* Joe Elwell <jelwell@netscape.com>
* H<EFBFBD>kan Waara <hwaara@chello.se>
* Aaron Kaluszka <ask@swva.net>
* Jeremy Morton <jez9999@runbox.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MAX_BUF
#define MAX_BUF 4096
#endif
// Implementation utilities.
#include "nsIDOMWindowInternal.h"
#include "nsIServiceManager.h"
#include "nsIPromptService.h"
#include "nsIStringBundle.h"
#include "nsIAllocator.h"
#include "nsXPIDLString.h"
#include "nsString.h"
#include "nsMemory.h"
#include "nsNetUtil.h"
#include "nsWindowsHooks.h"
#include <windows.h>
#include <shlobj.h>
#include <shlguid.h>
// for set as wallpaper
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
#include "nsIFrame.h"
#include "nsIPresShell.h"
#include "nsIImageLoadingContent.h"
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsDirectoryServiceUtils.h"
#include "nsAppDirectoryServiceDefs.h"
#ifndef MOZ_XUL_APP
#include "nsICmdLineService.h"
#endif
#include "nsXPFEComponentsCID.h"
#include "nsEmbedCID.h"
#define RUNKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
static nsWindowsHooks *gWindowsHooks = nsnull;
// Implementation of the nsIWindowsHooksSettings interface.
// Use standard implementation of nsISupports stuff.
NS_IMPL_ISUPPORTS1( nsWindowsHooksSettings, nsIWindowsHooksSettings )
nsWindowsHooksSettings::nsWindowsHooksSettings() {
}
nsWindowsHooksSettings::~nsWindowsHooksSettings() {
}
// Generic getter.
NS_IMETHODIMP
nsWindowsHooksSettings::Get( PRBool *result, PRBool nsWindowsHooksSettings::*member ) {
NS_ENSURE_ARG( result );
NS_ENSURE_ARG( member );
*result = this->*member;
return NS_OK;
}
// Generic setter.
NS_IMETHODIMP
nsWindowsHooksSettings::Set( PRBool value, PRBool nsWindowsHooksSettings::*member ) {
NS_ENSURE_ARG( member );
this->*member = value;
return NS_OK;
}
// Macros to define specific getter/setter methods.
#define DEFINE_GETTER_AND_SETTER( attr, member ) \
NS_IMETHODIMP \
nsWindowsHooksSettings::Get##attr ( PRBool *result ) { \
return this->Get( result, &nsWindowsHooksSettings::member ); \
} \
NS_IMETHODIMP \
nsWindowsHooksSettings::Set##attr ( PRBool value ) { \
return this->Set( value, &nsWindowsHooksSettings::member ); \
}
// Define all the getter/setter methods:
DEFINE_GETTER_AND_SETTER( IsHandlingHTML, mHandleHTML )
DEFINE_GETTER_AND_SETTER( IsHandlingJPEG, mHandleJPEG )
DEFINE_GETTER_AND_SETTER( IsHandlingGIF, mHandleGIF )
DEFINE_GETTER_AND_SETTER( IsHandlingPNG, mHandlePNG )
DEFINE_GETTER_AND_SETTER( IsHandlingXBM, mHandleXBM )
DEFINE_GETTER_AND_SETTER( IsHandlingBMP, mHandleBMP )
DEFINE_GETTER_AND_SETTER( IsHandlingICO, mHandleICO )
DEFINE_GETTER_AND_SETTER( IsHandlingXML, mHandleXML )
DEFINE_GETTER_AND_SETTER( IsHandlingXHTML, mHandleXHTML )
DEFINE_GETTER_AND_SETTER( IsHandlingXUL, mHandleXUL )
DEFINE_GETTER_AND_SETTER( IsHandlingHTTP, mHandleHTTP )
DEFINE_GETTER_AND_SETTER( IsHandlingHTTPS, mHandleHTTPS )
DEFINE_GETTER_AND_SETTER( IsHandlingFTP, mHandleFTP )
DEFINE_GETTER_AND_SETTER( IsHandlingCHROME, mHandleCHROME )
DEFINE_GETTER_AND_SETTER( IsHandlingGOPHER, mHandleGOPHER )
DEFINE_GETTER_AND_SETTER( ShowDialog, mShowDialog )
DEFINE_GETTER_AND_SETTER( HaveBeenSet, mHaveBeenSet )
// Implementation of the nsIWindowsHooks interface.
// Use standard implementation of nsISupports stuff.
NS_IMPL_ISUPPORTS1( nsWindowsHooks, nsIWindowsHooks )
static const char *jpgExts[] = { ".jpg", ".jpe", ".jpeg", ".jfif", ".pjpeg", ".pjp", 0 };
static const char *gifExts[] = { ".gif", 0 };
static const char *pngExts[] = { ".png", 0 };
static const char *xbmExts[] = { ".xbm", 0 };
static const char *bmpExts[] = { ".bmp", ".rle", ".dib", 0 };
static const char *icoExts[] = { ".ico", 0 };
static const char *xmlExts[] = { ".xml", 0 };
static const char *xhtmExts[] = { ".xht", ".xhtml", 0 };
static const char *xulExts[] = { ".xul", 0 };
static const char *htmExts[] = { ".htm", ".html", ".shtml", 0 };
nsWindowsHooks::nsWindowsHooks()
: http( "http" ),
https( "https" ),
ftp( "ftp" ),
chrome( "chrome" ),
gopher( "gopher" ),
jpg( jpgExts, "MozillaJPEG", "JPEG Image", "jpegfile", "jpeg-file.ico"),
gif( gifExts, "MozillaGIF", "GIF Image", "giffile", "gif-file.ico"),
png( pngExts, "MozillaPNG", "PNG Image", "pngfile", "image-file.ico"),
xbm( xbmExts, "MozillaXBM", "XBM Image", "xbmfile", "image-file.ico"),
bmp( bmpExts, "MozillaBMP", "BMP Image", "", "image-file.ico"),
ico( icoExts, "MozillaICO", "Icon", "icofile", "%1"),
xml( xmlExts, "MozillaXML", "XML Document", "xmlfile", "xml-file.ico"),
xhtml( xhtmExts, "MozillaXHTML", "XHTML Document", "", "misc-file.ico"),
xul( xulExts, "MozillaXUL", "Mozilla XUL Document", "", "xul-file.ico"),
mozillaMarkup( htmExts, "MozillaHTML", "HTML Document", "htmlfile", "html-file.ico")
{
gWindowsHooks = this;
}
nsWindowsHooks::~nsWindowsHooks() {
gWindowsHooks = nsnull;
}
// Internal GetPreferences.
NS_IMETHODIMP
nsWindowsHooks::GetSettings( nsWindowsHooksSettings **result ) {
nsresult rv = NS_OK;
// Validate input arg.
NS_ENSURE_ARG( result );
// Allocate prefs object.
nsWindowsHooksSettings *prefs = *result = new nsWindowsHooksSettings;
NS_ENSURE_TRUE( prefs, NS_ERROR_OUT_OF_MEMORY );
// Got it, increment ref count.
NS_ADDREF( prefs );
// Get each registry value and copy to prefs structure.
prefs->mHandleHTTP = BoolRegistryEntry( "isHandlingHTTP" );
prefs->mHandleHTTPS = BoolRegistryEntry( "isHandlingHTTPS" );
prefs->mHandleFTP = BoolRegistryEntry( "isHandlingFTP" );
prefs->mHandleCHROME = BoolRegistryEntry( "isHandlingCHROME" );
prefs->mHandleGOPHER = BoolRegistryEntry( "isHandlingGOPHER" );
prefs->mHandleHTML = BoolRegistryEntry( "isHandlingHTML" );
prefs->mHandleJPEG = BoolRegistryEntry( "isHandlingJPEG" );
prefs->mHandleGIF = BoolRegistryEntry( "isHandlingGIF" );
prefs->mHandlePNG = BoolRegistryEntry( "isHandlingPNG" );
prefs->mHandleXBM = BoolRegistryEntry( "isHandlingXBM" );
prefs->mHandleBMP = BoolRegistryEntry( "isHandlingBMP" );
prefs->mHandleICO = BoolRegistryEntry( "isHandlingICO" );
prefs->mHandleXML = BoolRegistryEntry( "isHandlingXML" );
prefs->mHandleXHTML = BoolRegistryEntry( "isHandlingXHTML" );
prefs->mHandleXUL = BoolRegistryEntry( "isHandlingXUL" );
prefs->mShowDialog = BoolRegistryEntry( "showDialog" );
prefs->mHaveBeenSet = BoolRegistryEntry( "haveBeenSet" );
#ifdef DEBUG_law
NS_ASSERTION( NS_SUCCEEDED( rv ), "GetPreferences failed" );
#endif
return rv;
}
// Public interface uses internal plus a QI to get to the proper result.
NS_IMETHODIMP
nsWindowsHooks::GetSettings( nsIWindowsHooksSettings **_retval ) {
// Allocate prefs object.
nsWindowsHooksSettings *prefs;
nsresult rv = this->GetSettings( &prefs );
if ( NS_SUCCEEDED( rv ) ) {
// QI to proper interface.
rv = prefs->QueryInterface( NS_GET_IID( nsIWindowsHooksSettings ), (void**)_retval );
// Release (to undo our Get...).
NS_RELEASE( prefs );
}
return rv;
}
static PRBool misMatch( const PRBool &flag, const ProtocolRegistryEntry &entry ) {
PRBool result = PR_FALSE;
// Check if we care.
if ( flag ) {
// Compare registry entry setting to what it *should* be.
if ( entry.currentSetting() != entry.setting ) {
result = PR_TRUE;
}
}
return result;
}
// isAccessRestricted - Returns PR_TRUE iff this user only has restricted access
// to the registry keys we need to modify.
static PRBool isAccessRestricted() {
char subKey[] = "Software\\Mozilla - Test Key";
PRBool result = PR_FALSE;
DWORD dwDisp = 0;
HKEY key;
// Try to create/open a subkey under HKLM.
DWORD rc = ::RegCreateKeyEx( HKEY_LOCAL_MACHINE,
subKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&key,
&dwDisp );
if ( rc == ERROR_SUCCESS ) {
// Key was opened; first close it.
::RegCloseKey( key );
// Delete it if we just created it.
switch( dwDisp ) {
case REG_CREATED_NEW_KEY:
::RegDeleteKey( HKEY_LOCAL_MACHINE, subKey );
break;
case REG_OPENED_EXISTING_KEY:
break;
}
} else {
// Can't create/open it; we don't have access.
result = PR_TRUE;
}
return result;
}
// Implementation of method that checks whether the settings match what's in the
// Windows registry.
NS_IMETHODIMP
nsWindowsHooksSettings::GetRegistryMatches( PRBool *_retval ) {
NS_ENSURE_ARG( _retval );
*_retval = PR_TRUE;
// Test registry for all selected attributes.
if ( misMatch( mHandleHTTP, gWindowsHooks->http )
||
misMatch( mHandleHTTPS, gWindowsHooks->https )
||
misMatch( mHandleFTP, gWindowsHooks->ftp )
||
misMatch( mHandleCHROME, gWindowsHooks->chrome )
||
misMatch( mHandleGOPHER, gWindowsHooks->gopher )
||
misMatch( mHandleHTML, gWindowsHooks->mozillaMarkup )
||
misMatch( mHandleJPEG, gWindowsHooks->jpg )
||
misMatch( mHandleGIF, gWindowsHooks->gif )
||
misMatch( mHandlePNG, gWindowsHooks->png )
||
misMatch( mHandleXBM, gWindowsHooks->xbm )
||
misMatch( mHandleBMP, gWindowsHooks->bmp )
||
misMatch( mHandleICO, gWindowsHooks->ico )
||
misMatch( mHandleXML, gWindowsHooks->xml )
||
misMatch( mHandleXHTML, gWindowsHooks->xhtml )
||
misMatch( mHandleXUL, gWindowsHooks->xul ) ) {
// Registry is out of synch.
*_retval = PR_FALSE;
}
return NS_OK;
}
// Implementation of method that checks settings versus registry and prompts user
// if out of synch.
NS_IMETHODIMP
nsWindowsHooks::CheckSettings( nsIDOMWindowInternal *aParent,
PRBool *_retval ) {
nsresult rv = NS_OK;
*_retval = PR_FALSE;
// Only do this once!
static PRBool alreadyChecked = PR_FALSE;
if ( alreadyChecked ) {
return NS_OK;
} else {
alreadyChecked = PR_TRUE;
// Don't check further if we don't have sufficient access.
if ( isAccessRestricted() ) {
return NS_OK;
}
}
// Get settings.
nsWindowsHooksSettings *settings;
rv = this->GetSettings( &settings );
if ( NS_SUCCEEDED( rv ) && settings ) {
// If not set previously, set to defaults so that they are
// set properly when/if the user says to.
if ( !settings->mHaveBeenSet ) {
settings->mHandleHTTP = PR_TRUE;
settings->mHandleHTTPS = PR_TRUE;
settings->mHandleFTP = PR_TRUE;
settings->mHandleCHROME = PR_TRUE;
settings->mHandleGOPHER = PR_TRUE;
settings->mHandleHTML = PR_TRUE;
settings->mHandleJPEG = PR_FALSE;
settings->mHandleGIF = PR_FALSE;
settings->mHandlePNG = PR_FALSE;
settings->mHandleXBM = PR_FALSE;
settings->mHandleBMP = PR_FALSE;
settings->mHandleICO = PR_FALSE;
settings->mHandleXML = PR_TRUE;
settings->mHandleXHTML = PR_TRUE;
settings->mHandleXUL = PR_TRUE;
settings->mShowDialog = PR_TRUE;
}
// If launched with "-installer" then override mShowDialog.
PRBool installing = PR_FALSE;
#ifndef MOZ_XUL_APP
if ( !settings->mShowDialog ) {
// Get command line service.
nsCOMPtr<nsICmdLineService> cmdLineArgs
(do_GetService(NS_COMMANDLINESERVICE_CONTRACTID, &rv));
if ( NS_SUCCEEDED( rv ) && cmdLineArgs ) {
// See if "-installer" was specified.
nsXPIDLCString installer;
rv = cmdLineArgs->GetCmdLineValue( "-installer", getter_Copies( installer ) );
if ( NS_SUCCEEDED( rv ) && installer ) {
installing = PR_TRUE;
}
}
}
#endif
// First, make sure the user cares.
if ( settings->mShowDialog || installing ) {
// Look at registry setting for all things that are set.
PRBool matches = PR_TRUE;
settings->GetRegistryMatches( &matches );
if ( !matches ) {
// Need to prompt user.
// First:
// o We need the common dialog service to show the dialog.
// o We need the string bundle service to fetch the appropriate
// dialog text.
nsCOMPtr<nsIPromptService> promptService( do_GetService(NS_PROMPTSERVICE_CONTRACTID));
nsCOMPtr<nsIStringBundleService> bundleService( do_GetService( NS_STRINGBUNDLE_CONTRACTID, &rv ) );
if ( promptService && bundleService ) {
// Next, get bundle that provides text for dialog.
nsCOMPtr<nsIStringBundle> bundle;
nsCOMPtr<nsIStringBundle> brandBundle;
rv = bundleService->CreateBundle( "chrome://global-platform/locale/nsWindowsHooks.properties",
getter_AddRefs( bundle ) );
rv = bundleService->CreateBundle( "chrome://branding/locale/brand.properties",
getter_AddRefs( brandBundle ) );
if ( NS_SUCCEEDED( rv ) && bundle && brandBundle ) {
nsXPIDLString text, label, shortName;
if ( NS_SUCCEEDED( ( rv = brandBundle->GetStringFromName( NS_LITERAL_STRING( "brandShortName" ).get(),
getter_Copies( shortName ) ) ) ) ) {
const PRUnichar* formatStrings[] = { shortName.get() };
if ( NS_SUCCEEDED( ( rv = bundle->FormatStringFromName( NS_LITERAL_STRING( "promptText" ).get(),
formatStrings, 1, getter_Copies( text ) ) ) )
&&
NS_SUCCEEDED( ( rv = bundle->GetStringFromName( NS_LITERAL_STRING( "checkBoxLabel" ).get(),
getter_Copies( label ) ) ) ) ) {
// Got the text, now show dialog.
PRBool showDialog = settings->mShowDialog;
PRInt32 dlgResult = -1;
// No checkbox for initial display.
const PRUnichar *labelArg = 0;
if ( settings->mHaveBeenSet ) {
// Subsequent display uses label string.
labelArg = label;
}
// Note that the buttons need to be passed in this order:
// o Yes
// o Cancel
// o No
rv = promptService->ConfirmEx(aParent, shortName, text,
(nsIPromptService::BUTTON_TITLE_YES * nsIPromptService::BUTTON_POS_0) +
(nsIPromptService::BUTTON_TITLE_CANCEL * nsIPromptService::BUTTON_POS_1) +
(nsIPromptService::BUTTON_TITLE_NO * nsIPromptService::BUTTON_POS_2),
nsnull, nsnull, nsnull, labelArg, &showDialog, &dlgResult);
if ( NS_SUCCEEDED( rv ) ) {
// Dialog was shown
*_retval = PR_TRUE;
// Did they say go ahead?
switch ( dlgResult ) {
case 0:
// User says: make the changes.
// Remember "show dialog" choice.
settings->mShowDialog = showDialog;
// Apply settings; this single line of
// code will do different things depending
// on whether this is the first time (i.e.,
// when "haveBeenSet" is false). The first
// time, this will set all prefs to true
// (because that's how we initialized 'em
// in GetSettings, above) and will update the
// registry accordingly. On subsequent passes,
// this will only update the registry (because
// the settings we got from GetSettings will
// not have changed).
//
// BTW, the term "prefs" in this context does not
// refer to conventional Mozilla "prefs." Instead,
// it refers to "Desktop Integration" prefs which
// are stored in the windows registry.
rv = SetSettings( settings );
#ifdef DEBUG_law
printf( "Yes, SetSettings returned 0x%08X\n", (int)rv );
#endif
break;
case 2:
// User says: Don't mess with Windows.
// We update only the "showDialog" and
// "haveBeenSet" keys. Note that this will
// have the effect of setting all the prefs
// *off* if the user says no to the initial
// prompt.
BoolRegistryEntry( "haveBeenSet" ).set();
if ( showDialog ) {
BoolRegistryEntry( "showDialog" ).set();
} else {
BoolRegistryEntry( "showDialog" ).reset();
}
#ifdef DEBUG_law
printf( "No, haveBeenSet=1 and showDialog=%d\n", (int)showDialog );
#endif
break;
default:
// User says: I dunno. Make no changes (which
// should produce the same dialog next time).
#ifdef DEBUG_law
printf( "Cancel\n" );
#endif
break;
}
}
}
}
}
}
}
#ifdef DEBUG_law
else { printf( "Registry and prefs match\n" ); }
#endif
}
#ifdef DEBUG_law
else { printf( "showDialog is false and not installing\n" ); }
#endif
// Release the settings.
settings->Release();
}
return rv;
}
// Utility to set PRBool registry value from getter method.
nsresult putPRBoolIntoRegistry( const char* valueName,
nsIWindowsHooksSettings *prefs,
nsWindowsHooksSettings::getter memFun ) {
// Use getter method to extract attribute from prefs.
PRBool boolValue;
(void)(prefs->*memFun)( &boolValue );
// Convert to DWORD.
DWORD dwordValue = boolValue;
// Store into registry.
BoolRegistryEntry pref( valueName );
nsresult rv = boolValue ? pref.set() : pref.reset();
return rv;
}
/* void setPreferences (in nsIWindowsHooksSettings prefs); */
NS_IMETHODIMP
nsWindowsHooks::SetSettings(nsIWindowsHooksSettings *prefs) {
nsresult rv = NS_ERROR_FAILURE;
putPRBoolIntoRegistry( "isHandlingHTTP", prefs, &nsIWindowsHooksSettings::GetIsHandlingHTTP );
putPRBoolIntoRegistry( "isHandlingHTTPS", prefs, &nsIWindowsHooksSettings::GetIsHandlingHTTPS );
putPRBoolIntoRegistry( "isHandlingFTP", prefs, &nsIWindowsHooksSettings::GetIsHandlingFTP );
putPRBoolIntoRegistry( "isHandlingCHROME", prefs, &nsIWindowsHooksSettings::GetIsHandlingCHROME );
putPRBoolIntoRegistry( "isHandlingGOPHER", prefs, &nsIWindowsHooksSettings::GetIsHandlingGOPHER );
putPRBoolIntoRegistry( "isHandlingHTML", prefs, &nsIWindowsHooksSettings::GetIsHandlingHTML );
putPRBoolIntoRegistry( "isHandlingJPEG", prefs, &nsIWindowsHooksSettings::GetIsHandlingJPEG );
putPRBoolIntoRegistry( "isHandlingGIF", prefs, &nsIWindowsHooksSettings::GetIsHandlingGIF );
putPRBoolIntoRegistry( "isHandlingPNG", prefs, &nsIWindowsHooksSettings::GetIsHandlingPNG );
putPRBoolIntoRegistry( "isHandlingXBM", prefs, &nsIWindowsHooksSettings::GetIsHandlingXBM );
putPRBoolIntoRegistry( "isHandlingBMP", prefs, &nsIWindowsHooksSettings::GetIsHandlingBMP );
putPRBoolIntoRegistry( "isHandlingICO", prefs, &nsIWindowsHooksSettings::GetIsHandlingICO );
putPRBoolIntoRegistry( "isHandlingXML", prefs, &nsIWindowsHooksSettings::GetIsHandlingXML );
putPRBoolIntoRegistry( "isHandlingXHTML", prefs, &nsIWindowsHooksSettings::GetIsHandlingXHTML );
putPRBoolIntoRegistry( "isHandlingXUL", prefs, &nsIWindowsHooksSettings::GetIsHandlingXUL );
putPRBoolIntoRegistry( "showDialog", prefs, &nsIWindowsHooksSettings::GetShowDialog );
// Indicate that these settings have indeed been set.
BoolRegistryEntry( "haveBeenSet" ).set();
rv = SetRegistry();
return rv;
}
// Get preferences and start handling everything selected.
NS_IMETHODIMP
nsWindowsHooks::SetRegistry() {
nsresult rv = NS_OK;
// Get raw prefs object.
nsWindowsHooksSettings *prefs;
rv = this->GetSettings( &prefs );
NS_ENSURE_TRUE( NS_SUCCEEDED( rv ), rv );
if ( prefs->mHandleHTML ) {
(void) mozillaMarkup.set();
} else {
(void) mozillaMarkup.reset();
}
if ( prefs->mHandleJPEG ) {
(void) jpg.set();
} else {
(void) jpg.reset();
}
if ( prefs->mHandleGIF ) {
(void) gif.set();
} else {
(void) gif.reset();
}
if ( prefs->mHandlePNG ) {
(void) png.set();
} else {
(void) png.reset();
}
if ( prefs->mHandleXBM ) {
(void) xbm.set();
} else {
(void) xbm.reset();
}
if ( prefs->mHandleBMP ) {
(void) bmp.set();
} else {
(void) bmp.reset();
}
if ( prefs->mHandleICO ) {
(void) ico.set();
} else {
(void) ico.reset();
}
if ( prefs->mHandleXML ) {
(void) xml.set();
} else {
(void) xml.reset();
}
if ( prefs->mHandleXHTML ) {
(void) xhtml.set();
} else {
(void) xhtml.reset();
}
if ( prefs->mHandleXUL ) {
(void) xul.set();
} else {
(void) xul.reset();
}
if ( prefs->mHandleHTTP ) {
(void) http.set();
} else {
(void) http.reset();
}
if ( prefs->mHandleHTTPS ) {
(void) https.set();
} else {
(void) https.reset();
}
if ( prefs->mHandleFTP ) {
(void) ftp.set();
} else {
(void) ftp.reset();
}
if ( prefs->mHandleCHROME ) {
(void) chrome.set();
} else {
(void) chrome.reset();
}
if ( prefs->mHandleGOPHER ) {
(void) gopher.set();
} else {
(void) gopher.reset();
}
// Call SHChangeNotify() to notify the windows shell that file
// associations changed, and that an update of the icons need to occur.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
return NS_OK;
}
// nsIWindowsHooks.idl for documentation
/*
* Name: IsOptionEnabled
* Arguments:
* PRUnichar* option - the option line switch we check to see if it is in the registry key
*
* Return Value:
* PRBool* _retval - PR_TRUE if option is already in the registry key, otherwise PR_FALSE
*
* Description:
* This function merely checks if the passed in string exists in the (appname) Quick Launch Key or not.
*
* Author:
* Joseph Elwell 3/1/2002
*/
NS_IMETHODIMP nsWindowsHooks::IsOptionEnabled(const char* option, PRBool *_retval) {
NS_ASSERTION(option, "nsWindowsHooks::IsOptionEnabled requires something like \"-turbo\"");
*_retval = PR_FALSE;
RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL );
nsCString cargs = startup.currentSetting();
if (cargs.Find(option, PR_TRUE) != kNotFound)
*_retval = PR_TRUE;
return NS_OK;
}
/*
* Name: grabArgs
* Arguments:
* char* optionline - the full optionline as read from the (appname) Quick Launch registry key
*
* Return Value:
* char** args - A pointer to the arguments (string in optionline)
* passed to the executable in the (appname) Quick Launch registry key
*
* Description:
* This function separates out the arguments from the optinline string
* Returning a pointer into the first arguments buffer.
* This function is used only locally, and is meant to reduce code size and readability.
*
* Author:
* Joseph Elwell 3/1/2002
*/
void grabArgs(char* optionline, char** args) {
nsCRT::strtok(optionline, "\"", &optionline);
if (optionline != NULL)
*args = nsCRT::strtok(optionline, "\"", &optionline);
}
/*
* Name: StartupAddOption
* Arguments:
* PRUnichar* option - the option line switch we want to add to the registry key
*
* Return Value: none
*
* Description:
* This function adds the given option line argument to the (appname) Quick Launch registry key
*
* Author:
* Joseph Elwell 3/1/2002
*/
NS_IMETHODIMP nsWindowsHooks::StartupAddOption(const char* option) {
NS_ASSERTION(option, "nsWindowsHooks::StartupAddOption requires something like \"-turbo\"");
PRBool retval;
IsOptionEnabled(option, &retval);
if (retval) return NS_OK; //already in there
RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL );
nsCString cargs = startup.currentSetting();
nsCAutoString newsetting;
newsetting.Assign('\"');
newsetting.Append(thisApplication());
newsetting.Append('\"');
if (!cargs.IsEmpty())
{
char* args;
// exploiting the fact that nsString's storage is also a char* buffer.
// NS_CONST_CAST is safe here because nsCRT::strtok will only modify
// the existing buffer
grabArgs(cargs.BeginWriting(), &args);
if (args != NULL)
newsetting.Append(args);
else
{
// check for the old style registry key that doesnot quote its executable
IsOptionEnabled("-turbo", &retval);
if (retval)
newsetting.Append(" -turbo");
}
}
newsetting.Append(' ');
newsetting.Append(option);
startup.setting = newsetting;
startup.set();
return NS_OK;
}
/*
* Name: StartupRemoveOption
* Arguments:
* PRUnichar* option - the option line switch we want to remove from the registry key
*
* Return Value: none.
*
* Description:
* This function removes the given option from the (appname) Quick Launch Key.
* And deletes the key entirely if no options are left.
*
* Author:
* Joseph Elwell 3/1/2002
*/
NS_IMETHODIMP nsWindowsHooks::StartupRemoveOption(const char* option) {
NS_ASSERTION(option, "nsWindowsHooks::StartupRemoveOption requires something like \"-turbo\"");
PRBool startupFound;
IsOptionEnabled(option, &startupFound );
if ( !startupFound )
return NS_OK; // already disabled, no need to do anything
RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL );
nsCString cargs = startup.currentSetting();
char* args;
// exploiting the fact that nsString's storage is also a char* buffer.
// NS_CONST_CAST is safe here because nsCRT::strtok will only modify
// the existing buffer
grabArgs(cargs.BeginWriting(), &args);
nsCAutoString launchcommand;
if (args)
{
launchcommand.Assign(args);
PRInt32 optionlocation = launchcommand.Find(option, PR_TRUE);
// modify by one to get rid of the space we prepended in StartupAddOption
if (optionlocation != kNotFound)
launchcommand.Cut(optionlocation - 1, strlen(option) + 1);
}
if (launchcommand.IsEmpty())
{
startup.set();
}
else
{
nsCAutoString ufileName;
ufileName.Assign('\"');
ufileName.Append(thisApplication());
ufileName.Append('\"');
ufileName.Append(launchcommand);
startup.setting = ufileName;
startup.set();
}
return NS_OK;
}
nsresult
WriteBitmap(nsIFile* aFile, gfxIImageFrame* aImage)
{
PRInt32 width, height;
aImage->GetWidth(&width);
aImage->GetHeight(&height);
PRUint8* bits;
PRUint32 length;
aImage->LockImageData();
aImage->GetImageData(&bits, &length);
if (!bits) {
aImage->UnlockImageData();
return NS_ERROR_FAILURE;
}
PRUint32 bpr;
aImage->GetImageBytesPerRow(&bpr);
PRInt32 bitCount = bpr/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)bitCount*8;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = length;
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
nsresult rv;
nsCOMPtr<nsIOutputStream> stream;
rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
NS_ENSURE_SUCCESS(rv, rv);
// write the bitmap headers and rgb pixel data to the file
rv = NS_ERROR_FAILURE;
if (stream) {
PRUint32 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
PRUint32 i = length;
rv = NS_OK;
do {
i -= bpr;
stream->Write(((const char*)bits) + i, bpr, &written);
if (written != bpr) {
rv = NS_ERROR_FAILURE;
break;
}
} while (i != 0);
}
}
stream->Close();
}
aImage->UnlockImageData();
return rv;
}
NS_IMETHODIMP
nsWindowsHooks::SetImageAsWallpaper(nsIDOMElement* aElement, PRBool aUseBackground)
{
nsresult rv;
nsCOMPtr<gfxIImageFrame> gfxFrame;
if (aUseBackground) {
// XXX write background loading stuff!
} 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;
nsCOMPtr<imgIContainer> container;
rv = request->GetImage(getter_AddRefs(container));
if (!container)
return NS_ERROR_FAILURE;
// get the current frame, which holds the image data
container->GetCurrentFrame(getter_AddRefs(gfxFrame));
}
if (!gfxFrame)
return NS_ERROR_FAILURE;
// get the profile root directory
nsCOMPtr<nsIFile> file;
rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR,
getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
// get the product brand name from localized strings
nsXPIDLString brandName, fileLeafName;
nsCOMPtr<nsIStringBundleService> bundleService =
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
NS_ENSURE_TRUE(bundleService, rv);
// get the product brand name from localized strings
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle("chrome://branding/locale/brand.properties",
getter_AddRefs(bundle));
NS_ENSURE_SUCCESS(rv, rv);
rv = bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
getter_Copies(brandName));
NS_ENSURE_SUCCESS(rv, rv);
// get the file leaf name from localized strings (e.g. "%S Wallpaper.bmp")
rv = bundleService->CreateBundle("chrome://global-platform/locale/nsWindowsHooks.properties",
getter_AddRefs(bundle));
NS_ENSURE_SUCCESS(rv, rv);
const PRUnichar* stringArray[] = { brandName.get() };
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("wallpaperFile").get(),
stringArray, NS_ARRAY_LENGTH(stringArray),
getter_Copies(fileLeafName));
NS_ENSURE_SUCCESS(rv, rv);
// eventually, the path is %APPDATA%\Mozilla\Mozilla Wallpaper.bmp
fileLeafName.AppendLiteral(".bmp");
rv = file->Append(fileLeafName);
NS_ENSURE_SUCCESS(rv, rv);
// write the bitmap to the target file
rv = WriteBitmap(file, gfxFrame);
NS_ENSURE_SUCCESS(rv, rv);
// set it as the system wallpaper
nsCAutoString nativePath;
rv = file->GetNativePath(nativePath);
NS_ENSURE_SUCCESS(rv, rv);
::SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID) nativePath.get(),
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
return rv;
}