Back to index

lightning-sunbird  0.9+nobinonly
nsWindowsHooks.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Bill Law       <law@netscape.com>
00024  *   Syd Logan      <syd@netscape.com> added turbo mode stuff
00025  *   Joe Elwell     <jelwell@netscape.com>
00026  *   Håkan Waara    <hwaara@chello.se>
00027  *   Aaron Kaluszka <ask@swva.net>
00028  *   Jeremy Morton  <jez9999@runbox.com>
00029  *
00030  * Alternatively, the contents of this file may be used under the terms of
00031  * either of the GNU General Public License Version 2 or later (the "GPL"),
00032  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00033  * in which case the provisions of the GPL or the LGPL are applicable instead
00034  * of those above. If you wish to allow use of your version of this file only
00035  * under the terms of either the GPL or the LGPL, and not to allow others to
00036  * use your version of this file under the terms of the MPL, indicate your
00037  * decision by deleting the provisions above and replace them with the notice
00038  * and other provisions required by the GPL or the LGPL. If you do not delete
00039  * the provisions above, a recipient may use your version of this file under
00040  * the terms of any one of the MPL, the GPL or the LGPL.
00041  *
00042  * ***** END LICENSE BLOCK ***** */
00043 
00044 #ifndef MAX_BUF
00045 #define MAX_BUF 4096
00046 #endif
00047 
00048 // Implementation utilities.
00049 #include "nsIDOMWindowInternal.h"
00050 #include "nsIServiceManager.h"
00051 #include "nsIPromptService.h"
00052 #include "nsIStringBundle.h"
00053 #include "nsIAllocator.h"
00054 #include "nsXPIDLString.h"
00055 #include "nsString.h"
00056 #include "nsMemory.h"
00057 #include "nsNetUtil.h"
00058 #include "nsWindowsHooksUtil.cpp"
00059 #include "nsWindowsHooks.h"
00060 #include <windows.h>
00061 #include <shlobj.h>
00062 #include <shlguid.h>
00063 
00064 // for set as wallpaper
00065 #include "nsIDocument.h"
00066 #include "nsIContent.h"
00067 #include "nsIDOMElement.h"
00068 #include "nsIDOMDocument.h"
00069 #include "nsIFrame.h"
00070 #include "nsIPresShell.h"
00071 #include "nsIImageLoadingContent.h"
00072 #include "imgIRequest.h"
00073 #include "imgIContainer.h"
00074 #include "gfxIImageFrame.h"
00075 #include "nsDirectoryServiceUtils.h"
00076 #include "nsAppDirectoryServiceDefs.h"
00077 
00078 #ifndef MOZ_XUL_APP
00079 #include "nsICmdLineService.h"
00080 #endif
00081 
00082 #include "nsXPFEComponentsCID.h"
00083 #include "nsEmbedCID.h"
00084 
00085 #define RUNKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
00086 
00087 // Objects that describe the Windows registry entries that we need to tweak.
00088 static ProtocolRegistryEntry
00089     http( "http" ),
00090     https( "https" ),
00091     ftp( "ftp" ),
00092     chrome( "chrome" ),
00093     gopher( "gopher" );
00094 const char *jpgExts[]  = { ".jpg", ".jpe", ".jpeg", ".jfif", ".pjpeg", ".pjp", 0 };
00095 const char *gifExts[]  = { ".gif", 0 };
00096 const char *pngExts[]  = { ".png", 0 };
00097 const char *mngExts[]  = { ".mng", 0 };
00098 const char *xbmExts[]  = { ".xbm", 0 };
00099 const char *bmpExts[]  = { ".bmp", ".rle", ".dib", 0 };
00100 const char *icoExts[]  = { ".ico", 0 };
00101 const char *xmlExts[]  = { ".xml", 0 };
00102 const char *xhtmExts[] = { ".xht", ".xhtml", 0 };
00103 const char *xulExts[]  = { ".xul", 0 };
00104 const char *htmExts[]  = { ".htm", ".html", ".shtml", 0 };
00105 
00106 static FileTypeRegistryEntry
00107     jpg(   jpgExts,  "MozillaJPEG",  "JPEG Image",           "jpegfile", "jpeg-file.ico"),
00108     gif(   gifExts,  "MozillaGIF",   "GIF Image",            "giffile",  "gif-file.ico"),
00109     png(   pngExts,  "MozillaPNG",   "PNG Image",            "pngfile",  "image-file.ico"),
00110     mng(   mngExts,  "MozillaMNG",   "MNG Image",            "",         "image-file.ico"),
00111     xbm(   xbmExts,  "MozillaXBM",   "XBM Image",            "xbmfile",  "image-file.ico"),
00112     bmp(   bmpExts,  "MozillaBMP",   "BMP Image",            "",         "image-file.ico"),
00113     ico(   icoExts,  "MozillaICO",   "Icon",                 "icofile",  "%1"),
00114     xml(   xmlExts,  "MozillaXML",   "XML Document",         "xmlfile",  "xml-file.ico"),
00115     xhtml( xhtmExts, "MozillaXHTML", "XHTML Document",       "",         "misc-file.ico"),
00116     xul(   xulExts,  "MozillaXUL",   "Mozilla XUL Document", "",         "xul-file.ico");
00117 
00118 static EditableFileTypeRegistryEntry
00119     mozillaMarkup( htmExts, "MozillaHTML", "HTML Document", "htmlfile",  "html-file.ico");
00120 
00121 // Implementation of the nsIWindowsHooksSettings interface.
00122 // Use standard implementation of nsISupports stuff.
00123 NS_IMPL_ISUPPORTS1( nsWindowsHooksSettings, nsIWindowsHooksSettings )
00124 
00125 nsWindowsHooksSettings::nsWindowsHooksSettings() {
00126 }
00127 
00128 nsWindowsHooksSettings::~nsWindowsHooksSettings() {
00129 }
00130 
00131 // Generic getter.
00132 NS_IMETHODIMP
00133 nsWindowsHooksSettings::Get( PRBool *result, PRBool nsWindowsHooksSettings::*member ) {
00134     NS_ENSURE_ARG( result );
00135     NS_ENSURE_ARG( member );
00136     *result = this->*member;
00137     return NS_OK;
00138 }
00139 
00140 // Generic setter.
00141 NS_IMETHODIMP
00142 nsWindowsHooksSettings::Set( PRBool value, PRBool nsWindowsHooksSettings::*member ) {
00143     NS_ENSURE_ARG( member );
00144     this->*member = value;
00145     return NS_OK;
00146 }
00147 
00148 // Macros to define specific getter/setter methods.
00149 #define DEFINE_GETTER_AND_SETTER( attr, member ) \
00150 NS_IMETHODIMP \
00151 nsWindowsHooksSettings::Get##attr ( PRBool *result ) { \
00152     return this->Get( result, &nsWindowsHooksSettings::member ); \
00153 } \
00154 NS_IMETHODIMP \
00155 nsWindowsHooksSettings::Set##attr ( PRBool value ) { \
00156     return this->Set( value, &nsWindowsHooksSettings::member ); \
00157 }
00158 
00159 // Define all the getter/setter methods:
00160 DEFINE_GETTER_AND_SETTER( IsHandlingHTML,   mHandleHTML   )
00161 DEFINE_GETTER_AND_SETTER( IsHandlingJPEG,   mHandleJPEG   )
00162 DEFINE_GETTER_AND_SETTER( IsHandlingGIF,    mHandleGIF    )
00163 DEFINE_GETTER_AND_SETTER( IsHandlingPNG,    mHandlePNG    )
00164 DEFINE_GETTER_AND_SETTER( IsHandlingMNG,    mHandleMNG    )
00165 DEFINE_GETTER_AND_SETTER( IsHandlingXBM,    mHandleXBM    )
00166 DEFINE_GETTER_AND_SETTER( IsHandlingBMP,    mHandleBMP    )
00167 DEFINE_GETTER_AND_SETTER( IsHandlingICO,    mHandleICO    )
00168 DEFINE_GETTER_AND_SETTER( IsHandlingXML,    mHandleXML    )
00169 DEFINE_GETTER_AND_SETTER( IsHandlingXHTML,  mHandleXHTML  )
00170 DEFINE_GETTER_AND_SETTER( IsHandlingXUL,    mHandleXUL    )
00171 DEFINE_GETTER_AND_SETTER( IsHandlingHTTP,   mHandleHTTP   )
00172 DEFINE_GETTER_AND_SETTER( IsHandlingHTTPS,  mHandleHTTPS  )
00173 DEFINE_GETTER_AND_SETTER( IsHandlingFTP,    mHandleFTP    )
00174 DEFINE_GETTER_AND_SETTER( IsHandlingCHROME, mHandleCHROME )
00175 DEFINE_GETTER_AND_SETTER( IsHandlingGOPHER, mHandleGOPHER )
00176 DEFINE_GETTER_AND_SETTER( ShowDialog,       mShowDialog   )
00177 DEFINE_GETTER_AND_SETTER( HaveBeenSet,      mHaveBeenSet  )
00178 
00179 
00180 // Implementation of the nsIWindowsHooks interface.
00181 // Use standard implementation of nsISupports stuff.
00182 NS_IMPL_ISUPPORTS1( nsWindowsHooks, nsIWindowsHooks )
00183 
00184 nsWindowsHooks::nsWindowsHooks() {
00185 }
00186 
00187 nsWindowsHooks::~nsWindowsHooks() {
00188 }
00189 
00190 // Internal GetPreferences.
00191 NS_IMETHODIMP
00192 nsWindowsHooks::GetSettings( nsWindowsHooksSettings **result ) {
00193     nsresult rv = NS_OK;
00194 
00195     // Validate input arg.
00196     NS_ENSURE_ARG( result );
00197 
00198     // Allocate prefs object.
00199     nsWindowsHooksSettings *prefs = *result = new nsWindowsHooksSettings;
00200     NS_ENSURE_TRUE( prefs, NS_ERROR_OUT_OF_MEMORY );
00201 
00202     // Got it, increment ref count.
00203     NS_ADDREF( prefs );
00204 
00205     // Get each registry value and copy to prefs structure.
00206     prefs->mHandleHTTP   = BoolRegistryEntry( "isHandlingHTTP"   );
00207     prefs->mHandleHTTPS  = BoolRegistryEntry( "isHandlingHTTPS"  );
00208     prefs->mHandleFTP    = BoolRegistryEntry( "isHandlingFTP"    );
00209     prefs->mHandleCHROME = BoolRegistryEntry( "isHandlingCHROME" );
00210     prefs->mHandleGOPHER = BoolRegistryEntry( "isHandlingGOPHER" );
00211     prefs->mHandleHTML   = BoolRegistryEntry( "isHandlingHTML"   );
00212     prefs->mHandleJPEG   = BoolRegistryEntry( "isHandlingJPEG"   );
00213     prefs->mHandleGIF    = BoolRegistryEntry( "isHandlingGIF"    );
00214     prefs->mHandlePNG    = BoolRegistryEntry( "isHandlingPNG"    );
00215     prefs->mHandleMNG    = BoolRegistryEntry( "isHandlingMNG"    );
00216     prefs->mHandleXBM    = BoolRegistryEntry( "isHandlingXBM"    );
00217     prefs->mHandleBMP    = BoolRegistryEntry( "isHandlingBMP"    );
00218     prefs->mHandleICO    = BoolRegistryEntry( "isHandlingICO"    );
00219     prefs->mHandleXML    = BoolRegistryEntry( "isHandlingXML"    );
00220     prefs->mHandleXHTML  = BoolRegistryEntry( "isHandlingXHTML"  );
00221     prefs->mHandleXUL    = BoolRegistryEntry( "isHandlingXUL"    );
00222     prefs->mShowDialog   = BoolRegistryEntry( "showDialog"       );
00223     prefs->mHaveBeenSet  = BoolRegistryEntry( "haveBeenSet"      );
00224 
00225 #ifdef DEBUG_law
00226 NS_WARN_IF_FALSE( NS_SUCCEEDED( rv ), "GetPreferences failed" );
00227 #endif
00228 
00229     return rv;
00230 }
00231 
00232 // Public interface uses internal plus a QI to get to the proper result.
00233 NS_IMETHODIMP
00234 nsWindowsHooks::GetSettings( nsIWindowsHooksSettings **_retval ) {
00235     // Allocate prefs object.
00236     nsWindowsHooksSettings *prefs;
00237     nsresult rv = this->GetSettings( &prefs );
00238 
00239     if ( NS_SUCCEEDED( rv ) ) {
00240         // QI to proper interface.
00241         rv = prefs->QueryInterface( NS_GET_IID( nsIWindowsHooksSettings ), (void**)_retval );
00242         // Release (to undo our Get...).
00243         NS_RELEASE( prefs );
00244     }
00245 
00246     return rv;
00247 }
00248 
00249 static PRBool misMatch( const PRBool &flag, const ProtocolRegistryEntry &entry ) {
00250     PRBool result = PR_FALSE;
00251     // Check if we care.
00252     if ( flag ) { 
00253         // Compare registry entry setting to what it *should* be.
00254         if ( entry.currentSetting() != entry.setting ) {
00255             result = PR_TRUE;
00256         }
00257     }
00258 
00259     return result;
00260 }
00261 
00262 // isAccessRestricted - Returns PR_TRUE iff this user only has restricted access
00263 // to the registry keys we need to modify.
00264 static PRBool isAccessRestricted() {
00265     char   subKey[] = "Software\\Mozilla - Test Key";
00266     PRBool result = PR_FALSE;
00267     DWORD  dwDisp = 0;
00268     HKEY   key;
00269     // Try to create/open a subkey under HKLM.
00270     DWORD rc = ::RegCreateKeyEx( HKEY_LOCAL_MACHINE,
00271                                  subKey,
00272                                  0,
00273                                  NULL,
00274                                  REG_OPTION_NON_VOLATILE,
00275                                  KEY_WRITE,
00276                                  NULL,
00277                                  &key,
00278                                  &dwDisp );
00279 
00280     if ( rc == ERROR_SUCCESS ) {
00281         // Key was opened; first close it.
00282         ::RegCloseKey( key );
00283         // Delete it if we just created it.
00284         switch( dwDisp ) {
00285             case REG_CREATED_NEW_KEY:
00286                 ::RegDeleteKey( HKEY_LOCAL_MACHINE, subKey );
00287                 break;
00288             case REG_OPENED_EXISTING_KEY:
00289                 break;
00290         }
00291     } else {
00292         // Can't create/open it; we don't have access.
00293         result = PR_TRUE;
00294     }
00295 
00296     return result;
00297 }
00298 
00299 
00300 
00301 // Implementation of method that checks whether the settings match what's in the
00302 // Windows registry.
00303 NS_IMETHODIMP
00304 nsWindowsHooksSettings::GetRegistryMatches( PRBool *_retval ) {
00305     NS_ENSURE_ARG( _retval );
00306     *_retval = PR_TRUE;
00307     // Test registry for all selected attributes.
00308     if ( misMatch( mHandleHTTP,   http )
00309          ||
00310          misMatch( mHandleHTTPS,  https )
00311          ||
00312          misMatch( mHandleFTP,    ftp )
00313          ||
00314          misMatch( mHandleCHROME, chrome )
00315          ||
00316          misMatch( mHandleGOPHER, gopher )
00317          ||
00318          misMatch( mHandleHTML,   mozillaMarkup )
00319          ||
00320          misMatch( mHandleJPEG,   jpg )
00321          ||
00322          misMatch( mHandleGIF,    gif )
00323          ||
00324          misMatch( mHandlePNG,    png )
00325          ||
00326          misMatch( mHandleMNG,    mng )
00327          ||
00328          misMatch( mHandleXBM,    xbm )
00329          ||
00330          misMatch( mHandleBMP,    bmp )
00331          ||
00332          misMatch( mHandleICO,    ico )
00333          ||
00334          misMatch( mHandleXML,    xml )
00335          ||
00336          misMatch( mHandleXHTML,  xhtml )
00337          ||
00338          misMatch( mHandleXUL,    xul ) ) {
00339         // Registry is out of synch.
00340         *_retval = PR_FALSE;
00341     }
00342     return NS_OK;
00343 }
00344 
00345 // Implementation of method that checks settings versus registry and prompts user
00346 // if out of synch.
00347 NS_IMETHODIMP
00348 nsWindowsHooks::CheckSettings( nsIDOMWindowInternal *aParent, 
00349                                PRBool *_retval ) {
00350     nsresult rv = NS_OK;
00351     *_retval = PR_FALSE;
00352 
00353     // Only do this once!
00354     static PRBool alreadyChecked = PR_FALSE;
00355     if ( alreadyChecked ) {
00356         return NS_OK;
00357     } else {
00358         alreadyChecked = PR_TRUE;
00359         // Don't check further if we don't have sufficient access.
00360         if ( isAccessRestricted() ) {
00361             return NS_OK;
00362         }
00363     }
00364 
00365     // Get settings.
00366     nsWindowsHooksSettings *settings;
00367     rv = this->GetSettings( &settings );
00368 
00369     if ( NS_SUCCEEDED( rv ) && settings ) {
00370         // If not set previously, set to defaults so that they are
00371         // set properly when/if the user says to.
00372         if ( !settings->mHaveBeenSet ) {
00373             settings->mHandleHTTP   = PR_TRUE;
00374             settings->mHandleHTTPS  = PR_TRUE;
00375             settings->mHandleFTP    = PR_TRUE;
00376             settings->mHandleCHROME = PR_TRUE;
00377             settings->mHandleGOPHER = PR_TRUE;
00378             settings->mHandleHTML   = PR_TRUE;
00379             settings->mHandleJPEG   = PR_FALSE;
00380             settings->mHandleGIF    = PR_FALSE;
00381             settings->mHandlePNG    = PR_FALSE;
00382             settings->mHandleMNG    = PR_FALSE;
00383             settings->mHandleXBM    = PR_FALSE;
00384             settings->mHandleBMP    = PR_FALSE;
00385             settings->mHandleICO    = PR_FALSE;
00386             settings->mHandleXML    = PR_TRUE;
00387             settings->mHandleXHTML  = PR_TRUE;
00388             settings->mHandleXUL    = PR_TRUE;
00389 
00390             settings->mShowDialog   = PR_TRUE;
00391         }
00392 
00393         // If launched with "-installer" then override mShowDialog.
00394         PRBool installing = PR_FALSE;
00395 #ifndef MOZ_XUL_APP
00396         if ( !settings->mShowDialog ) {
00397             // Get command line service.
00398             nsCOMPtr<nsICmdLineService> cmdLineArgs
00399               (do_GetService(NS_COMMANDLINESERVICE_CONTRACTID, &rv));
00400             if ( NS_SUCCEEDED( rv ) && cmdLineArgs ) {
00401                 // See if "-installer" was specified.
00402                 nsXPIDLCString installer;
00403                 rv = cmdLineArgs->GetCmdLineValue( "-installer", getter_Copies( installer ) );
00404                 if ( NS_SUCCEEDED( rv ) && installer ) {
00405                     installing = PR_TRUE;
00406                 }
00407             }
00408         }
00409 #endif
00410 
00411         // First, make sure the user cares.
00412         if ( settings->mShowDialog || installing ) {
00413             // Look at registry setting for all things that are set.
00414             PRBool matches = PR_TRUE;
00415             settings->GetRegistryMatches( &matches );
00416             if ( !matches ) {
00417                 // Need to prompt user.
00418                 // First:
00419                 //   o We need the common dialog service to show the dialog.
00420                 //   o We need the string bundle service to fetch the appropriate
00421                 //     dialog text.
00422                 nsCOMPtr<nsIPromptService> promptService( do_GetService(NS_PROMPTSERVICE_CONTRACTID));
00423                 nsCOMPtr<nsIStringBundleService> bundleService( do_GetService( NS_STRINGBUNDLE_CONTRACTID, &rv ) );
00424 
00425                 if ( promptService && bundleService ) {
00426                     // Next, get bundle that provides text for dialog.
00427                     nsCOMPtr<nsIStringBundle> bundle;
00428                     nsCOMPtr<nsIStringBundle> brandBundle;
00429                     rv = bundleService->CreateBundle( "chrome://global-platform/locale/nsWindowsHooks.properties",
00430                                                       getter_AddRefs( bundle ) );
00431                     rv = bundleService->CreateBundle( "chrome://branding/locale/brand.properties",
00432                                                       getter_AddRefs( brandBundle ) );
00433                     if ( NS_SUCCEEDED( rv ) && bundle && brandBundle ) {
00434                         nsXPIDLString text, label, shortName;
00435                         if ( NS_SUCCEEDED( ( rv = brandBundle->GetStringFromName( NS_LITERAL_STRING( "brandShortName" ).get(), 
00436                                              getter_Copies( shortName ) ) ) ) ) {
00437                             const PRUnichar* formatStrings[] = { shortName.get() };
00438                             if ( NS_SUCCEEDED( ( rv = bundle->FormatStringFromName( NS_LITERAL_STRING( "promptText" ).get(), 
00439                                                   formatStrings, 1, getter_Copies( text ) ) ) )
00440                                   &&
00441                                   NS_SUCCEEDED( ( rv = bundle->GetStringFromName( NS_LITERAL_STRING( "checkBoxLabel" ).get(),
00442                                                                                   getter_Copies( label ) ) ) ) ) {
00443                                 // Got the text, now show dialog.
00444                                 PRBool  showDialog = settings->mShowDialog;
00445                                 PRInt32 dlgResult  = -1;
00446                                 // No checkbox for initial display.
00447                                 const PRUnichar *labelArg = 0;
00448                                 if ( settings->mHaveBeenSet ) {
00449                                     // Subsequent display uses label string.
00450                                     labelArg = label;
00451                                 }
00452                                 // Note that the buttons need to be passed in this order:
00453                                 //    o Yes
00454                                 //    o Cancel
00455                                 //    o No
00456                                 rv = promptService->ConfirmEx(aParent, shortName, text,
00457                                                               (nsIPromptService::BUTTON_TITLE_YES * nsIPromptService::BUTTON_POS_0) +
00458                                                               (nsIPromptService::BUTTON_TITLE_CANCEL * nsIPromptService::BUTTON_POS_1) +
00459                                                               (nsIPromptService::BUTTON_TITLE_NO * nsIPromptService::BUTTON_POS_2),
00460                                                               nsnull, nsnull, nsnull, labelArg, &showDialog, &dlgResult);
00461                                 
00462                                 if ( NS_SUCCEEDED( rv ) ) {
00463                                     // Dialog was shown
00464                                     *_retval = PR_TRUE; 
00465 
00466                                     // Did they say go ahead?
00467                                     switch ( dlgResult ) {
00468                                         case 0:
00469                                             // User says: make the changes.
00470                                             // Remember "show dialog" choice.
00471                                             settings->mShowDialog = showDialog;
00472                                             // Apply settings; this single line of
00473                                             // code will do different things depending
00474                                             // on whether this is the first time (i.e.,
00475                                             // when "haveBeenSet" is false).  The first
00476                                             // time, this will set all prefs to true
00477                                             // (because that's how we initialized 'em
00478                                             // in GetSettings, above) and will update the
00479                                             // registry accordingly.  On subsequent passes,
00480                                             // this will only update the registry (because
00481                                             // the settings we got from GetSettings will
00482                                             // not have changed).
00483                                             //
00484                                             // BTW, the term "prefs" in this context does not
00485                                             // refer to conventional Mozilla "prefs."  Instead,
00486                                             // it refers to "Desktop Integration" prefs which
00487                                             // are stored in the windows registry.
00488                                             rv = SetSettings( settings );
00489                                             #ifdef DEBUG_law
00490                                                 printf( "Yes, SetSettings returned 0x%08X\n", (int)rv );
00491                                             #endif
00492                                             break;
00493 
00494                                         case 2:
00495                                             // User says: Don't mess with Windows.
00496                                             // We update only the "showDialog" and
00497                                             // "haveBeenSet" keys.  Note that this will
00498                                             // have the effect of setting all the prefs
00499                                             // *off* if the user says no to the initial
00500                                             // prompt.
00501                                             BoolRegistryEntry( "haveBeenSet" ).set();
00502                                             if ( showDialog ) {
00503                                                 BoolRegistryEntry( "showDialog" ).set();
00504                                             } else {
00505                                                 BoolRegistryEntry( "showDialog" ).reset();
00506                                             }
00507                                             #ifdef DEBUG_law
00508                                                 printf( "No, haveBeenSet=1 and showDialog=%d\n", (int)showDialog );
00509                                             #endif
00510                                             break;
00511 
00512                                         default:
00513                                             // User says: I dunno.  Make no changes (which
00514                                             // should produce the same dialog next time).
00515                                             #ifdef DEBUG_law
00516                                                 printf( "Cancel\n" );
00517                                             #endif
00518                                             break;
00519                                     }
00520                                 }
00521                             }
00522                         }
00523                     }
00524                 }
00525             }
00526             #ifdef DEBUG_law
00527             else { printf( "Registry and prefs match\n" ); }
00528             #endif
00529         }
00530         #ifdef DEBUG_law
00531         else { printf( "showDialog is false and not installing\n" ); }
00532         #endif
00533 
00534         // Release the settings.
00535         settings->Release();
00536     }
00537 
00538     return rv;
00539 }
00540 
00541 // Utility to set PRBool registry value from getter method.
00542 nsresult putPRBoolIntoRegistry( const char* valueName,
00543                                 nsIWindowsHooksSettings *prefs,
00544                                 nsWindowsHooksSettings::getter memFun ) {
00545     // Use getter method to extract attribute from prefs.
00546     PRBool boolValue;
00547     (void)(prefs->*memFun)( &boolValue );
00548     // Convert to DWORD.
00549     DWORD  dwordValue = boolValue;
00550     // Store into registry.
00551     BoolRegistryEntry pref( valueName );
00552     nsresult rv = boolValue ? pref.set() : pref.reset();
00553 
00554     return rv;
00555 }
00556 
00557 /* void setPreferences (in nsIWindowsHooksSettings prefs); */
00558 NS_IMETHODIMP
00559 nsWindowsHooks::SetSettings(nsIWindowsHooksSettings *prefs) {
00560     nsresult rv = NS_ERROR_FAILURE;
00561 
00562     putPRBoolIntoRegistry( "isHandlingHTTP",   prefs, &nsIWindowsHooksSettings::GetIsHandlingHTTP );
00563     putPRBoolIntoRegistry( "isHandlingHTTPS",  prefs, &nsIWindowsHooksSettings::GetIsHandlingHTTPS );
00564     putPRBoolIntoRegistry( "isHandlingFTP",    prefs, &nsIWindowsHooksSettings::GetIsHandlingFTP );
00565     putPRBoolIntoRegistry( "isHandlingCHROME", prefs, &nsIWindowsHooksSettings::GetIsHandlingCHROME );
00566     putPRBoolIntoRegistry( "isHandlingGOPHER", prefs, &nsIWindowsHooksSettings::GetIsHandlingGOPHER );
00567     putPRBoolIntoRegistry( "isHandlingHTML",   prefs, &nsIWindowsHooksSettings::GetIsHandlingHTML );
00568     putPRBoolIntoRegistry( "isHandlingJPEG",   prefs, &nsIWindowsHooksSettings::GetIsHandlingJPEG );
00569     putPRBoolIntoRegistry( "isHandlingGIF",    prefs, &nsIWindowsHooksSettings::GetIsHandlingGIF );
00570     putPRBoolIntoRegistry( "isHandlingPNG",    prefs, &nsIWindowsHooksSettings::GetIsHandlingPNG );
00571     putPRBoolIntoRegistry( "isHandlingMNG",    prefs, &nsIWindowsHooksSettings::GetIsHandlingMNG );
00572     putPRBoolIntoRegistry( "isHandlingXBM",    prefs, &nsIWindowsHooksSettings::GetIsHandlingXBM );
00573     putPRBoolIntoRegistry( "isHandlingBMP",    prefs, &nsIWindowsHooksSettings::GetIsHandlingBMP );
00574     putPRBoolIntoRegistry( "isHandlingICO",    prefs, &nsIWindowsHooksSettings::GetIsHandlingICO );
00575     putPRBoolIntoRegistry( "isHandlingXML",    prefs, &nsIWindowsHooksSettings::GetIsHandlingXML );
00576     putPRBoolIntoRegistry( "isHandlingXHTML",  prefs, &nsIWindowsHooksSettings::GetIsHandlingXHTML );
00577     putPRBoolIntoRegistry( "isHandlingXUL",    prefs, &nsIWindowsHooksSettings::GetIsHandlingXUL );
00578     putPRBoolIntoRegistry( "showDialog",       prefs, &nsIWindowsHooksSettings::GetShowDialog );
00579 
00580     // Indicate that these settings have indeed been set.
00581     BoolRegistryEntry( "haveBeenSet" ).set();
00582 
00583     rv = SetRegistry();
00584 
00585     return rv;
00586 }
00587 
00588 // Get preferences and start handling everything selected.
00589 NS_IMETHODIMP
00590 nsWindowsHooks::SetRegistry() {
00591     nsresult rv = NS_OK;
00592 
00593     // Get raw prefs object.
00594     nsWindowsHooksSettings *prefs;
00595     rv = this->GetSettings( &prefs );
00596 
00597     NS_ENSURE_TRUE( NS_SUCCEEDED( rv ), rv );
00598 
00599     if ( prefs->mHandleHTML ) {
00600         (void) mozillaMarkup.set();
00601     } else {
00602         (void) mozillaMarkup.reset();
00603     }
00604     if ( prefs->mHandleJPEG ) {
00605         (void) jpg.set();
00606     } else {
00607         (void) jpg.reset();
00608     }
00609     if ( prefs->mHandleGIF ) {
00610         (void) gif.set();
00611     } else {
00612         (void) gif.reset();
00613     }
00614     if ( prefs->mHandlePNG ) {
00615         (void) png.set();
00616     } else {
00617         (void) png.reset();
00618     }
00619     if ( prefs->mHandleMNG ) {
00620         (void) mng.set();
00621     } else {
00622         (void) mng.reset();
00623     }
00624     if ( prefs->mHandleXBM ) {
00625         (void) xbm.set();
00626     } else {
00627         (void) xbm.reset();
00628     }
00629     if ( prefs->mHandleBMP ) {
00630         (void) bmp.set();
00631     } else {
00632         (void) bmp.reset();
00633     }
00634     if ( prefs->mHandleICO ) {
00635         (void) ico.set();
00636     } else {
00637         (void) ico.reset();
00638     }
00639     if ( prefs->mHandleXML ) {
00640         (void) xml.set();
00641     } else {
00642         (void) xml.reset();
00643     }
00644     if ( prefs->mHandleXHTML ) {
00645         (void) xhtml.set();
00646     } else {
00647         (void) xhtml.reset();
00648     }
00649     if ( prefs->mHandleXUL ) {
00650         (void) xul.set();
00651     } else {
00652         (void) xul.reset();
00653     }
00654     if ( prefs->mHandleHTTP ) {
00655         (void) http.set();
00656     } else {
00657         (void) http.reset();
00658     }
00659     if ( prefs->mHandleHTTPS ) {
00660         (void) https.set();
00661     } else {
00662         (void) https.reset();
00663     }
00664     if ( prefs->mHandleFTP ) {
00665         (void) ftp.set();
00666     } else {
00667         (void) ftp.reset();
00668     }
00669     if ( prefs->mHandleCHROME ) {
00670         (void) chrome.set();
00671     } else {
00672         (void) chrome.reset();
00673     }
00674     if ( prefs->mHandleGOPHER ) {
00675         (void) gopher.set();
00676     } else {
00677         (void) gopher.reset();
00678     }
00679 
00680     // Call SHChangeNotify() to notify the windows shell that file
00681     // associations changed, and that an update of the icons need to occur.
00682     SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
00683 
00684     return NS_OK;
00685 }
00686 
00687 // nsIWindowsHooks.idl for documentation
00688 
00689 /*
00690   * Name: IsOptionEnabled
00691   * Arguments:
00692   *     PRUnichar* option - the option line switch we check to see if it is in the registry key
00693   *
00694   * Return Value:
00695   *     PRBool* _retval - PR_TRUE if option is already in the registry key, otherwise PR_FALSE
00696   *
00697   * Description:
00698   *     This function merely checks if the passed in string exists in the (appname) Quick Launch Key or not.
00699   *
00700   * Author:
00701   *     Joseph Elwell 3/1/2002
00702 */
00703 NS_IMETHODIMP nsWindowsHooks::IsOptionEnabled(const char* option, PRBool *_retval) { 
00704     NS_ASSERTION(option, "nsWindowsHooks::IsOptionEnabled requires something like \"-turbo\"");
00705        *_retval = PR_FALSE;
00706     RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL );
00707     nsCString cargs = startup.currentSetting();
00708     if (cargs.Find(option, PR_TRUE) != kNotFound)
00709         *_retval = PR_TRUE;
00710     return NS_OK;
00711 }
00712 
00713 /*
00714   * Name: grabArgs
00715   * Arguments:
00716   *     char* optionline  - the full optionline as read from the (appname) Quick Launch registry key
00717   *
00718   * Return Value:
00719   *     char** args - A pointer to the arguments (string in optionline)
00720   *                   passed to the executable in the (appname) Quick Launch registry key
00721   *
00722   * Description:
00723   *     This function separates out the arguments from the optinline string
00724   *     Returning a pointer into the first arguments buffer.
00725   *     This function is used only locally, and is meant to reduce code size and readability.
00726   *
00727   * Author:
00728   *     Joseph Elwell 3/1/2002
00729 */
00730 void grabArgs(char* optionline, char** args) {
00731     nsCRT::strtok(optionline, "\"", &optionline);
00732     if (optionline != NULL)
00733         *args = nsCRT::strtok(optionline, "\"", &optionline);
00734 }
00735 
00736 /*
00737   * Name: StartupAddOption
00738   * Arguments:
00739   *     PRUnichar* option - the option line switch we want to add to the registry key
00740   *
00741   * Return Value: none
00742   *
00743   * Description:
00744   *     This function adds the given option line argument to the (appname) Quick Launch registry key
00745   *
00746   * Author:
00747   *     Joseph Elwell 3/1/2002
00748 */
00749 NS_IMETHODIMP nsWindowsHooks::StartupAddOption(const char* option) {
00750     NS_ASSERTION(option, "nsWindowsHooks::StartupAddOption requires something like \"-turbo\"");
00751     PRBool retval;
00752     IsOptionEnabled(option, &retval);
00753     if (retval) return NS_OK; //already in there
00754     
00755     RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL );
00756     nsCString cargs = startup.currentSetting();
00757     nsCAutoString newsetting;
00758     newsetting.Assign('\"');
00759     newsetting.Append(thisApplication());
00760     newsetting.Append('\"');
00761     if (!cargs.IsEmpty())
00762     {
00763         char* args;
00764         // exploiting the fact that nsString's storage is also a char* buffer.
00765         // NS_CONST_CAST is safe here because nsCRT::strtok will only modify
00766         // the existing buffer
00767         grabArgs(cargs.BeginWriting(), &args);
00768         if (args != NULL)
00769             newsetting.Append(args);
00770         else
00771         {
00772             // check for the old style registry key that doesnot quote its executable
00773             IsOptionEnabled("-turbo", &retval);
00774             if (retval)
00775                 newsetting.Append(" -turbo");
00776         }
00777     }
00778     newsetting.Append(' ');
00779     newsetting.Append(option);
00780     startup.setting = newsetting;
00781     startup.set();    
00782     return NS_OK;
00783 }
00784 
00785 /*
00786   * Name: StartupRemoveOption
00787   * Arguments:
00788   *     PRUnichar* option - the option line switch we want to remove from the registry key
00789   *
00790   * Return Value: none.
00791   *
00792   * Description:
00793   *     This function removes the given option from the (appname) Quick Launch Key.
00794   *     And deletes the key entirely if no options are left.
00795   *
00796   * Author:
00797   *     Joseph Elwell 3/1/2002
00798 */
00799 NS_IMETHODIMP nsWindowsHooks::StartupRemoveOption(const char* option) {
00800     NS_ASSERTION(option, "nsWindowsHooks::StartupRemoveOption requires something like \"-turbo\"");
00801     PRBool startupFound;
00802     IsOptionEnabled(option, &startupFound );
00803     if ( !startupFound )
00804         return NS_OK;               // already disabled, no need to do anything
00805 
00806     RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL );
00807     nsCString cargs = startup.currentSetting();
00808     char* args;
00809     // exploiting the fact that nsString's storage is also a char* buffer.
00810     // NS_CONST_CAST is safe here because nsCRT::strtok will only modify
00811     // the existing buffer
00812     grabArgs(cargs.BeginWriting(), &args);
00813 
00814     nsCAutoString launchcommand;
00815     if (args)
00816     {
00817         launchcommand.Assign(args);
00818         PRInt32 optionlocation = launchcommand.Find(option, PR_TRUE);
00819         // modify by one to get rid of the space we prepended in StartupAddOption
00820         if (optionlocation != kNotFound)
00821             launchcommand.Cut(optionlocation - 1, strlen(option) + 1);
00822     }
00823        
00824     if (launchcommand.IsEmpty())
00825     {
00826         startup.set();
00827     }
00828     else
00829     {
00830         nsCAutoString ufileName;
00831         ufileName.Assign('\"');
00832         ufileName.Append(thisApplication());
00833         ufileName.Append('\"');
00834         ufileName.Append(launchcommand);
00835         startup.setting = ufileName;
00836         startup.set();
00837     }
00838     return NS_OK;
00839 }
00840 
00841 nsresult
00842 WriteBitmap(nsIFile* aFile, gfxIImageFrame* aImage)
00843 {
00844   PRInt32 width, height;
00845   aImage->GetWidth(&width);
00846   aImage->GetHeight(&height);
00847   
00848   PRUint8* bits;
00849   PRUint32 length;
00850   aImage->GetImageData(&bits, &length);
00851   if (!bits) return NS_ERROR_FAILURE;
00852   
00853   PRUint32 bpr;
00854   aImage->GetImageBytesPerRow(&bpr);
00855   PRInt32 bitCount = bpr/width;
00856   
00857   // initialize these bitmap structs which we will later
00858   // serialize directly to the head of the bitmap file
00859   LPBITMAPINFOHEADER bmi = (LPBITMAPINFOHEADER)new BITMAPINFO;
00860   bmi->biSize = sizeof(BITMAPINFOHEADER);
00861   bmi->biWidth = width;
00862   bmi->biHeight = height;
00863   bmi->biPlanes = 1;
00864   bmi->biBitCount = (WORD)bitCount*8;
00865   bmi->biCompression = BI_RGB;
00866   bmi->biSizeImage = 0; // don't need to set this if bmp is uncompressed
00867   bmi->biXPelsPerMeter = 0;
00868   bmi->biYPelsPerMeter = 0;
00869   bmi->biClrUsed = 0;
00870   bmi->biClrImportant = 0;
00871   
00872   BITMAPFILEHEADER bf;
00873   bf.bfType = 0x4D42; // 'BM'
00874   bf.bfReserved1 = 0;
00875   bf.bfReserved2 = 0;
00876   bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
00877   bf.bfSize = bf.bfOffBits + bmi->biSizeImage;
00878 
00879   // get a file output stream
00880   nsresult rv;
00881   nsCOMPtr<nsIOutputStream> stream;
00882   rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
00883   NS_ENSURE_SUCCESS(rv, rv);
00884 
00885   // write the bitmap headers and rgb pixel data to the file
00886   rv = NS_ERROR_FAILURE;
00887   if (stream) {
00888     PRUint32 written;
00889     stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
00890     if (written == sizeof(BITMAPFILEHEADER)) {
00891       stream->Write((const char*)bmi, sizeof(BITMAPINFOHEADER), &written);
00892       if (written == sizeof(BITMAPINFOHEADER)) {
00893         stream->Write((const char*)bits, length, &written);
00894         if (written == length)
00895           rv = NS_OK;
00896       }
00897     }
00898   
00899     stream->Close();
00900   }
00901   
00902   return rv;
00903 }
00904 
00905 NS_IMETHODIMP
00906 nsWindowsHooks::SetImageAsWallpaper(nsIDOMElement* aElement, PRBool aUseBackground)
00907 {
00908   nsresult rv;
00909   
00910   nsCOMPtr<gfxIImageFrame> gfxFrame;
00911   if (aUseBackground) {
00912     // XXX write background loading stuff!
00913   } else {
00914     nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement, &rv);
00915     if (!imageContent) return rv;
00916     
00917     // get the image container
00918     nsCOMPtr<imgIRequest> request;
00919     rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
00920                                   getter_AddRefs(request));
00921     if (!request) return rv;
00922     nsCOMPtr<imgIContainer> container;
00923     rv = request->GetImage(getter_AddRefs(container));
00924     if (!container)
00925       return NS_ERROR_FAILURE;
00926     
00927     // get the current frame, which holds the image data
00928     container->GetCurrentFrame(getter_AddRefs(gfxFrame));
00929   }  
00930   
00931   if (!gfxFrame)
00932     return NS_ERROR_FAILURE;
00933 
00934   // get the profile root directory
00935   nsCOMPtr<nsIFile> file;
00936   rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR,
00937                               getter_AddRefs(file));
00938   NS_ENSURE_SUCCESS(rv, rv);
00939   
00940   // get the product brand name from localized strings
00941   nsXPIDLString brandName, fileLeafName;
00942   nsCOMPtr<nsIStringBundleService> bundleService =
00943            do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
00944   NS_ENSURE_TRUE(bundleService, rv);
00945 
00946   // get the product brand name from localized strings
00947   nsCOMPtr<nsIStringBundle> bundle;
00948   rv = bundleService->CreateBundle("chrome://branding/locale/brand.properties",
00949                                    getter_AddRefs(bundle));
00950   NS_ENSURE_SUCCESS(rv, rv);
00951 
00952   rv = bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
00953                                  getter_Copies(brandName));
00954   NS_ENSURE_SUCCESS(rv, rv);
00955 
00956   // get the file leaf name from localized strings (e.g. "%S Wallpaper.bmp")
00957   rv = bundleService->CreateBundle("chrome://global-platform/locale/nsWindowsHooks.properties",
00958                                    getter_AddRefs(bundle));
00959   NS_ENSURE_SUCCESS(rv, rv);
00960 
00961   const PRUnichar* stringArray[] = { brandName.get() };
00962 
00963   rv = bundle->FormatStringFromName(NS_LITERAL_STRING("wallpaperFile").get(),
00964                                     stringArray, NS_ARRAY_LENGTH(stringArray),
00965                                     getter_Copies(fileLeafName));
00966   NS_ENSURE_SUCCESS(rv, rv);
00967   
00968   // eventually, the path is %APPDATA%\Mozilla\Mozilla Wallpaper.bmp
00969   fileLeafName.AppendLiteral(".bmp");
00970   rv = file->Append(fileLeafName);
00971   NS_ENSURE_SUCCESS(rv, rv);
00972 
00973   // write the bitmap to the target file
00974   rv = WriteBitmap(file, gfxFrame);
00975   NS_ENSURE_SUCCESS(rv, rv);
00976 
00977   // set it as the system wallpaper
00978   nsCAutoString nativePath;
00979   rv = file->GetNativePath(nativePath);
00980   NS_ENSURE_SUCCESS(rv, rv);
00981   
00982   ::SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID) nativePath.get(),
00983                          SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
00984 
00985   return rv;
00986 }