Back to index

lightning-sunbird  0.9+nobinonly
CProfileManager.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Mozilla browser.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications, Inc.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Conrad Carlen <ccarlen@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 // PPBrowser
00041 #include "CProfileManager.h"
00042 #include "ApplIDs.h"
00043 #include "UMacUnicode.h"
00044 
00045 // PowerPlant
00046 #include <LEditText.h>
00047 #include <LTextTableView.h>
00048 #include <LPushButton.h>
00049 #include <LTableMonoGeometry.h>
00050 #include <LTableArrayStorage.h>
00051 #include <LTableSingleSelector.h>
00052 #include <LCheckBox.h>
00053 
00054 // Carbon
00055 #include <CFPreferences.h>
00056 
00057 // Mozilla
00058 #include "nsIProfile.h"
00059 #include "nsIDirectoryService.h"
00060 #include "nsDirectoryServiceDefs.h"
00061 #include "nsAppDirectoryServiceDefs.h"
00062 #include "nsIObserverService.h"
00063 #include "nsXPIDLString.h"
00064 #include "nsCRT.h"
00065 
00066 // ANSI
00067 #include <climits>
00068 
00069 // Constants
00070 
00071 const MessageT    msg_OnNewProfile                = 2000;
00072 const MessageT    msg_OnDeleteProfile         = 2001;
00073 const MessageT    msg_OnRenameProfile         = 2002;
00074 
00075 #define kPrefShowProfilesAtStartup "start-show-dialog"
00076 
00077 //*****************************************************************************
00078 //***    CProfileManager
00079 //*****************************************************************************
00080 
00081 CProfileManager::CProfileManager() :
00082     LAttachment(msg_AnyMessage,true)
00083 {
00084 }
00085 
00086 CProfileManager::~CProfileManager()
00087 {
00088 }
00089 
00090 void CProfileManager::StartUp()
00091 {
00092     nsresult rv;
00093          
00094     nsCOMPtr<nsIProfile> profileService = 
00095              do_GetService(NS_PROFILE_CONTRACTID, &rv);
00096     ThrowIfNil_(profileService);
00097         
00098     PRInt32 profileCount;
00099     rv = profileService->GetProfileCount(&profileCount);
00100     ThrowIfError_(rv);
00101     if (profileCount == 0)
00102     {
00103         // Make a new default profile
00104         NS_NAMED_LITERAL_STRING(newProfileName, "default");
00105 
00106         rv = profileService->CreateNewProfile(newProfileName.get(), nsnull, nsnull, PR_FALSE);
00107         ThrowIfError_(rv);
00108         rv = profileService->SetCurrentProfile(newProfileName.get());
00109         ThrowIfError_(rv);
00110     }
00111     else
00112     {
00113         // Use our flag here to check for whether to show profile mgr UI. If the flag
00114         // says don't show it, just start with the last used profile.
00115         
00116         PRBool showIt;
00117         rv = GetShowDialogOnStart(&showIt);
00118                         
00119         if (NS_FAILED(rv) || (profileCount > 1 && showIt))
00120         {
00121             DoManageProfilesDialog();
00122         }
00123         else
00124         {
00125             // GetCurrentProfile returns the profile which was last used but is not nescesarily
00126             // active. Call SetCurrentProfile to make it installed and active.
00127             
00128             nsXPIDLString   currProfileName;
00129             rv = profileService->GetCurrentProfile(getter_Copies(currProfileName));
00130             ThrowIfError_(rv);
00131             rv = profileService->SetCurrentProfile(currProfileName);
00132             ThrowIfError_(rv);
00133         }    
00134     }
00135 }
00136 
00137 Boolean CProfileManager::DoNewProfileDialog(char *outName, UInt32 bufSize)
00138 {
00139     Boolean confirmed;
00140     StDialogHandler  theHandler(dlog_NewProfile, LCommander::GetTopCommander());
00141     LWindow                  *theDialog = theHandler.GetDialog();
00142     
00143     ThrowIfNil_(theDialog);
00144     LEditText *responseText = dynamic_cast<LEditText*>(theDialog->FindPaneByID('Name'));
00145     ThrowIfNil_(responseText);
00146     theDialog->SetLatentSub(responseText);
00147 
00148     theDialog->Show();
00149     theDialog->Select();
00150        
00151        while (true)  // This is our modal dialog event loop
00152        {                           
00153               MessageT      hitMessage = theHandler.DoDialog();
00154               
00155               if (hitMessage == msg_OK)
00156               {
00157                   Str255 pStr;
00158                   UInt32 outLen;
00159                   
00160                   responseText->GetDescriptor(pStr);
00161                   outLen = pStr[0] >= bufSize ? bufSize - 1 : pStr[0];
00162                   memcpy(outName, &pStr[1], outLen);
00163                   outName[outLen] = '\0'; 
00164             confirmed = PR_TRUE;
00165               break;
00166               }
00167               else if (hitMessage == msg_Cancel)
00168               {
00169                   confirmed = PR_FALSE;
00170                   break;
00171               }
00172        }
00173        return confirmed;
00174 }
00175 
00176 
00177 void CProfileManager::DoManageProfilesDialog()
00178 {
00179     nsresult rv;
00180     StDialogHandler  theHandler(dlog_ManageProfiles, LCommander::GetTopCommander());
00181     LWindow                  *theDialog = theHandler.GetDialog();
00182 
00183     nsCOMPtr<nsIProfile> profileService = 
00184              do_GetService(NS_PROFILE_CONTRACTID, &rv);
00185     ThrowIfNil_(profileService);
00186         
00187     // Set up the dialog by filling the list of current profiles
00188     LTextTableView *table = (LTextTableView*) theDialog->FindPaneByID('List');    
00189     ThrowIfNil_(table);
00190     LPushButton *deleteButton = (LPushButton *) theDialog->FindPaneByID('Dele');
00191     ThrowIfNil_(deleteButton);
00192     
00193     //Str255 pascalStr;
00194     nsAutoString unicodeStr;
00195     nsCAutoString cStr;
00196     char dataBuf[256];
00197     UInt32 dataSize;
00198     
00199     // PowerPlant stuff to set up the list view
00200     STableCell selectedCell(1, 1);
00201     SDimension16 tableSize;
00202     TableIndexT rows, cols;
00203 
00204     table->GetFrameSize(tableSize);
00205        table->SetTableGeometry(new LTableMonoGeometry(table, tableSize.width, 16));
00206        table->SetTableStorage(new LTableArrayStorage(table, 0UL));
00207        table->SetTableSelector(new LTableSingleSelector(table));
00208        table->InsertCols(1, 0);
00209 
00210     // Get the name of the current profile so we can select it
00211     nsXPIDLString   currProfileName;
00212     profileService->GetCurrentProfile(getter_Copies(currProfileName));
00213     
00214     // Get the list of profile names and add them to the list
00215     PRUint32 listLen;
00216     PRUnichar **profileList;
00217     rv = profileService->GetProfileList(&listLen, &profileList);
00218     ThrowIfError_(rv);
00219     
00220     for (PRUint32 index = 0; index < listLen; index++)
00221     {
00222           CPlatformUCSConversion::GetInstance()->UCSToPlatform(nsDependentString(profileList[index]), cStr);
00223           table->InsertRows(1, LONG_MAX, cStr.get(), cStr.Length(), true);
00224           
00225           if (nsCRT::strcmp(profileList[index], currProfileName.get()) == 0)
00226             selectedCell.row = index + 1;
00227     }
00228     
00229     PRInt32 numProfiles;
00230     rv = profileService->GetProfileCount(&numProfiles);
00231     ThrowIfError_(rv);    
00232     (numProfiles > 1) ? deleteButton->Enable() : deleteButton->Disable();
00233     table->SelectCell(selectedCell);
00234 
00235 
00236     // Handle the "Ask At StartUp" checkbox    
00237     LCheckBox *showAtStartCheck = (LCheckBox*) theDialog->FindPaneByID('Show');
00238     ThrowIfNil_(showAtStartCheck);
00239     PRBool showIt;
00240     rv = GetShowDialogOnStart(&showIt);
00241     if (NS_FAILED(rv))
00242         showIt = PR_TRUE;
00243     showAtStartCheck->SetValue(showIt);
00244 
00245     
00246     theDialog->Show();
00247     theDialog->Select();
00248        
00249        while (true)  // This is our modal dialog event loop
00250        {                           
00251               MessageT      hitMessage = theHandler.DoDialog();
00252               
00253               if (hitMessage == msg_OK)
00254               {
00255                   theDialog->Hide();
00256             SetShowDialogOnStart(showAtStartCheck->GetValue());
00257                   selectedCell = table->GetFirstSelectedCell();
00258                   if (selectedCell.row > 0)
00259                   {
00260                       dataSize = sizeof(dataBuf) - 1;
00261                       table->GetCellData(selectedCell, dataBuf, dataSize);
00262                       dataBuf[dataSize] = '\0';
00263                 CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsDependentCString(dataBuf), unicodeStr);
00264                       rv = profileService->SetCurrentProfile(unicodeStr.get());
00265             }
00266                   break;
00267               }
00268         else if (hitMessage == msg_Cancel)
00269         {
00270               break;
00271         }
00272         else if (hitMessage == msg_OnNewProfile)
00273               {
00274                   if (DoNewProfileDialog(dataBuf, sizeof(dataBuf)))
00275                   {
00276                       CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsDependentCString(dataBuf), unicodeStr);
00277                       rv = profileService->CreateNewProfile(unicodeStr.get(), nsnull, nsnull, PR_FALSE);
00278                       if (NS_FAILED(rv))
00279                           break;
00280                       
00281                 table->InsertRows(1, LONG_MAX, dataBuf, strlen(dataBuf), true);
00282                 table->GetTableSize(rows, cols);
00283                 table->SelectCell(STableCell(rows, cols));
00284                 
00285                 rv = profileService->GetProfileCount(&numProfiles);
00286                 (NS_SUCCEEDED(rv) && numProfiles > 1) ? deleteButton->Enable() : deleteButton->Disable();
00287                   }    
00288               }
00289               else if (hitMessage == msg_OnDeleteProfile)
00290               {
00291                   selectedCell = table->GetFirstSelectedCell();
00292                   if (selectedCell.row > 0)
00293                   {
00294                       dataSize = sizeof(dataBuf) - 1;
00295                       table->GetCellData(selectedCell, dataBuf, dataSize);
00296                       dataBuf[dataSize] = '\0';
00297                       CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsDependentCString(dataBuf), unicodeStr);
00298                       
00299                       rv = profileService->DeleteProfile(unicodeStr.get(), PR_TRUE);
00300                       if (NS_FAILED(rv))
00301                           break;
00302                       
00303                       table->RemoveRows(1, selectedCell.row, true);
00304                       table->GetTableSize(rows, cols);    
00305                       if (selectedCell.row >= rows)
00306                           selectedCell.row = rows - 1;
00307                       table->SelectCell(selectedCell);
00308                       
00309                 rv = profileService->GetProfileCount(&numProfiles);
00310                 (NS_SUCCEEDED(rv) && numProfiles > 1) ? deleteButton->Enable() : deleteButton->Disable();
00311                   }
00312               }
00313               else if (hitMessage == msg_OnRenameProfile)
00314               {
00315                nsAutoString oldName;
00316 
00317                   selectedCell = table->GetFirstSelectedCell();
00318                dataSize = sizeof(dataBuf) - 1;
00319                table->GetCellData(selectedCell, dataBuf, dataSize);
00320                dataBuf[dataSize] = '\0';
00321                CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsDependentCString(dataBuf), oldName);
00322 
00323                   if (DoNewProfileDialog(dataBuf, sizeof(dataBuf)))
00324                   {
00325                       CPlatformUCSConversion::GetInstance()->PlatformToUCS(nsDependentCString(dataBuf), unicodeStr);
00326                 profileService->RenameProfile(oldName.get(), unicodeStr.get());
00327                 table->SetCellData(selectedCell, dataBuf, strlen(dataBuf));                 
00328                   }
00329               }
00330        }  
00331 }
00332 
00333 
00334 void CProfileManager::DoLogout()
00335 {
00336     enum { iPersist = 1, iCancel, iCleanse };
00337 
00338     nsresult rv;
00339     nsCOMPtr<nsIProfile> profileService = 
00340              do_GetService(NS_PROFILE_CONTRACTID, &rv);
00341     ThrowIfNil_(profileService);
00342     
00343     nsXPIDLString currentProfile;
00344     Str255 pStr;
00345     profileService->GetCurrentProfile(getter_Copies(currentProfile));
00346        CPlatformUCSConversion::GetInstance()->UCSToPlatform(nsDependentString(currentProfile.get()), pStr);
00347     ::ParamText(pStr, "\p", "\p", "\p");
00348     
00349     DialogItemIndex item = UModalAlerts::StopAlert(alrt_ConfirmLogout);
00350     if (item == iCancel)
00351       return;
00352 
00353     if (item == iPersist)
00354         rv = profileService->ShutDownCurrentProfile(nsIProfile::SHUTDOWN_PERSIST);
00355     else    
00356         rv = profileService->ShutDownCurrentProfile(nsIProfile::SHUTDOWN_CLEANSE);
00357     if (NS_SUCCEEDED(rv)) {
00358         // Just put this up modally until they pick a new profile
00359         DoManageProfilesDialog();
00360     }
00361 }
00362 
00363 
00364 /*
00365     The following three methods have nothing to do with profile management per se.
00366     They use the registry to store a flag which allows the user to choose whether
00367     to show the profile manager dialog at startup. After all, since we can switch
00368     it at any time - why must we deal with the dialog every time we start the app?
00369 */
00370 
00371 nsresult CProfileManager::GetShowDialogOnStart(PRBool* showIt)
00372 {
00373     *showIt = PR_TRUE;
00374 
00375     CFStringRef showDialogKey = CFSTR(kPrefShowProfilesAtStartup);
00376     Boolean keyExistsAndIsValid, value;
00377     
00378     value = CFPreferencesGetAppBooleanValue(showDialogKey,
00379                 kCFPreferencesCurrentApplication,
00380                 &keyExistsAndIsValid);
00381             
00382     if (!keyExistsAndIsValid)
00383       return NS_ERROR_FAILURE;
00384     *showIt = value;
00385     
00386     return NS_OK;
00387 }
00388 
00389 nsresult CProfileManager::SetShowDialogOnStart(PRBool showIt)
00390 {
00391     CFStringRef showDialogKey = CFSTR(kPrefShowProfilesAtStartup);
00392     
00393     CFPreferencesSetAppValue(showDialogKey,
00394       showIt ? kCFBooleanTrue : kCFBooleanFalse,
00395       kCFPreferencesCurrentApplication);
00396     
00397     // Write out the preference data - this is our 1 and only use of it.
00398     CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
00399     
00400     return NS_OK;
00401 }
00402 
00403 //*****************************************************************************
00404 //***    CProfileManager::LAttachment
00405 //*****************************************************************************
00406 
00407 void CProfileManager::ExecuteSelf(MessageT inMessage, void *ioParam)
00408 {
00409        mExecuteHost = true;
00410        // update status
00411        if (inMessage == msg_CommandStatus) {
00412               SCommandStatus       *status = (SCommandStatus *)ioParam;
00413               if (status->command == cmd_ManageProfiles) {
00414                      *status->enabled = true;
00415                      *status->usesMark = false;
00416                      mExecuteHost = false; // we handled it
00417               }
00418               else if (status->command == cmd_Logout) {
00419                      *status->enabled = true;
00420                      *status->usesMark = false;
00421                      mExecuteHost = false; // we handled it
00422               }
00423        }
00424        else if (inMessage == cmd_ManageProfiles) {
00425            DoManageProfilesDialog();
00426            mExecuteHost = false; // we handled it
00427        }
00428        else if (inMessage == cmd_Logout) {
00429            DoLogout();
00430            mExecuteHost = false; // we handled it
00431        }
00432 }