diff --git a/mozilla/mailnews/base/src/nsMsgAccountManager.cpp b/mozilla/mailnews/base/src/nsMsgAccountManager.cpp index e7cf75201e0..ed64d37e798 100644 --- a/mozilla/mailnews/base/src/nsMsgAccountManager.cpp +++ b/mozilla/mailnews/base/src/nsMsgAccountManager.cpp @@ -1414,6 +1414,7 @@ nsMsgAccountManager::LoadAccounts() } m_accountsLoaded = PR_TRUE; //It is ok to return null accounts like when we create new profile + m_haveShutdown = PR_FALSE; if (!accountList || !accountList[0]) { #ifdef DEBUG_ACCOUNTMANAGER diff --git a/mozilla/profile/public/nsIProfileChangeStatus.idl b/mozilla/profile/public/nsIProfileChangeStatus.idl index 8e0bd9050ac..bcf3735de5d 100755 --- a/mozilla/profile/public/nsIProfileChangeStatus.idl +++ b/mozilla/profile/public/nsIProfileChangeStatus.idl @@ -85,6 +85,9 @@ * did during its profile-do-change. For example, to respond to * new preferences. * + * "profile-initial-state" + * Called after all phases of a change have completed. Typically + * in this phase, an application level observer will open a new window. * * Contexts for profile changes. These are passed as the someData param to the * observer's Observe() method. diff --git a/mozilla/profile/public/nsIProfileInternal.idl b/mozilla/profile/public/nsIProfileInternal.idl index 026ef6ceb28..72607c234b8 100755 --- a/mozilla/profile/public/nsIProfileInternal.idl +++ b/mozilla/profile/public/nsIProfileInternal.idl @@ -84,8 +84,6 @@ interface nsIProfileInternal : nsIProfile { void getProfileListX(in unsigned long which, out unsigned long length, [retval, array, size_is(length)] out wstring profileNames); - void startApprunner(in wstring profileName); - void migrateProfileInfo(); void migrateAllProfiles(); void migrateProfile(in wstring profileName); @@ -119,6 +117,13 @@ interface nsIProfileInternal : nsIProfile { attribute boolean automigrate; readonly attribute nsIFile defaultProfileParentDir; readonly attribute wstring firstProfile; + + /** + * Affects startup behavior when there are multiple profiles. + * If FALSE, the profile selection dialog will be shown. + * If TRUE, the last used profile will be chosen automatically. + */ + attribute boolean startWithLastUsedProfile; [noscript] void updateRegistry(in nsIFile regName); [noscript] void getRegStrings(in wstring profileName, diff --git a/mozilla/profile/resources/content/createProfileWizard.js b/mozilla/profile/resources/content/createProfileWizard.js index 939154b0a51..291b8713505 100644 --- a/mozilla/profile/resources/content/createProfileWizard.js +++ b/mozilla/profile/resources/content/createProfileWizard.js @@ -103,7 +103,7 @@ function onFinish() window.opener.CreateProfile(profName, profDir); } else { - profile.startApprunner(profName); + profile.currentProfile = profName; } window.close(); } diff --git a/mozilla/profile/resources/content/profileManager.js b/mozilla/profile/resources/content/profileManager.js index 9911afd7c6b..70da7233415 100644 --- a/mozilla/profile/resources/content/profileManager.js +++ b/mozilla/profile/resources/content/profileManager.js @@ -281,10 +281,24 @@ function DoEnabling() else { if( renbutton.getAttribute( "disabled" ) == "true" ) renbutton.removeAttribute( "disabled", "true" ); - if( delbutton.getAttribute( "disabled" ) == "true" ) - delbutton.removeAttribute( "disabled", "true" ); if( start.getAttribute( "disabled" ) == "true" ) start.removeAttribute( "disabled", "true" ); + + var canDelete = true; + if (!gStartupMode) { + var selected = profileList.selectedItems[0]; + var profileName = selected.getAttribute("profile_name"); + var currentProfile = profile.currentProfile; + if (currentProfile && (profileName == currentProfile)) + canDelete = false; + } + if (canDelete) { + if ( delbutton.getAttribute( "disabled" ) == "true" ) + delbutton.removeAttribute( "disabled" ); + } + else + delbutton.setAttribute( "disabled", "true" ); + } } diff --git a/mozilla/profile/resources/content/profileSelection.js b/mozilla/profile/resources/content/profileSelection.js index b30db81abc6..0ebd3d8117e 100644 --- a/mozilla/profile/resources/content/profileSelection.js +++ b/mozilla/profile/resources/content/profileSelection.js @@ -24,6 +24,8 @@ * Dan Veditz */ +var gDialogParams; +var gStartupMode; // TRUE if we're being shown at app startup, FALSE if from menu. var gProfileManagerBundle; var gBrandBundle; var profile = Components.classes["@mozilla.org/profile/manager;1"].getService(); @@ -34,6 +36,10 @@ var Registry; function StartUp() { + gDialogParams = window.arguments[0]. + QueryInterface(Components.interfaces.nsIDialogParamBlock); + gStartupMode = (gDialogParams.GetString(0) == "startup"); + gProfileManagerBundle = document.getElementById("bundle_profileManager"); gBrandBundle = document.getElementById("bundle_brand"); @@ -41,6 +47,22 @@ function StartUp() centerWindowOnScreen(); if(window.location && window.location.search && window.location.search == "?manage=true" ) SwitchProfileManagerMode(); + + // Set up the intro text, depending on our context + var introTextItem = document.getElementById("intro"); + var introText, insertText; + if (gStartupMode) { + insertText = gProfileManagerBundle.getFormattedString("startButton", + [gBrandBundle.getString("brandShortName")]); + introText = gProfileManagerBundle.getFormattedString("intro_start", + [insertText]); + } + else { + insertText = gProfileManagerBundle.getString("selectButton"); + introText = gProfileManagerBundle.getFormattedString("intro_switch", + [insertText]); + } + introTextItem.childNodes[0].nodeValue = introText; var dirServ = Components.classes['@mozilla.org/file/directory_service;1'].createInstance(); dirServ = dirServ.QueryInterface(Components.interfaces.nsIProperties); @@ -62,16 +84,21 @@ function StartUp() loadElements(); highlightCurrentProfile(); - // set the checkbox to reflect the current state. var offlineState = document.getElementById("offlineState"); - try { - var ioService = nsJSComponentManager.getServiceByID("{9ac9e770-18bc-11d3-9337-00104ba0fd40}", - "nsIIOService"); + if (gStartupMode) { + // set the checkbox to reflect the current state. + var ioService = Components.classes["@mozilla.org/network/io-service;1"]. + getService(Components.interfaces.nsIIOService); offlineState.checked = ioService.offline; } - catch(e) { + else { + // hide the checkbox in this context + offlineState.hidden = true; } + var autoSelectLastProfile = document.getElementById("autoSelectLastProfile"); + autoSelectLastProfile.checked = profile.startWithLastUsedProfile; + var profileList = document.getElementById("profiles"); profileList.focus(); @@ -190,15 +217,19 @@ function onStart() } // start in online or offline mode - var offlineState = document.getElementById("offlineState"); - var ioService = nsJSComponentManager.getServiceByID("{9ac9e770-18bc-11d3-9337-00104ba0fd40}", - "nsIIOService"); - ioService.offline = offlineState.checked; - + if (gStartupMode) { + var offlineState = document.getElementById("offlineState"); + var ioService = Components.classes["@mozilla.org/network/io-service;1"]. + getService(Components.interfaces.nsIIOService); + if (offlineState.checked != ioService.offline) + ioService.offline = offlineState.checked; + } + + var autoSelectLastProfile = document.getElementById("autoSelectLastProfile"); + profile.startWithLastUsedProfile = autoSelectLastProfile.checked; + try { - // All this really does is set the current profile. - // It has nothing to do with starting the application. - profile.startApprunner(profilename); + profile.currentProfile = profilename; } catch (ex) { var brandName = gBrandBundle.getString("brandShortName"); @@ -219,6 +250,8 @@ function onStart() promptService.alert(window, null, message); return false; } + + gDialogParams.SetInt(0, 1); // 1 == success return true; } @@ -227,12 +260,7 @@ function onStart() // purpose : quits startup process (User Choice: "Exit") function onExit() { - try { - profile.forgetCurrentProfile(); - } - catch (ex) { - dump("Failed to forget current profile.\n"); - } + gDialogParams.SetInt(0, 0); // 0 == cancel return true; } @@ -244,12 +272,17 @@ function SetUpOKCancelButtons() var okButtonString; var cancelButtonString; - - try { - okButtonString = gProfileManagerBundle.getString("startButton"); - okButtonString = okButtonString.replace(/%brandShortName%/, - gBrandBundle.getString("brandShortName")); - cancelButtonString = gProfileManagerBundle.getString("exitButton"); + + try { + if (gStartupMode) { + okButtonString = gProfileManagerBundle.getFormattedString("startButton", + [gBrandBundle.getString("brandShortName")]); + cancelButtonString = gProfileManagerBundle.getString("exitButton"); + } + else { + okButtonString = gProfileManagerBundle.getString("selectButton"); + cancelButtonString = gProfileManagerBundle.getString("cancel"); + } } catch (e) { okButtonString = "Start Yah"; cancelButtonString = "Exit Yah"; diff --git a/mozilla/profile/resources/content/profileSelection.xul b/mozilla/profile/resources/content/profileSelection.xul index 30545f18fc5..8a1c3819847 100644 --- a/mozilla/profile/resources/content/profileSelection.xul +++ b/mozilla/profile/resources/content/profileSelection.xul @@ -64,7 +64,7 @@ - &introgeneral.label; + "" &pmTextA.label; @@ -90,9 +90,10 @@ - + - + + diff --git a/mozilla/profile/resources/locale/en-US/profileManager.properties b/mozilla/profile/resources/locale/en-US/profileManager.properties index 9b7edcd50a4..9525c3535e4 100644 --- a/mozilla/profile/resources/locale/en-US/profileManager.properties +++ b/mozilla/profile/resources/locale/en-US/profileManager.properties @@ -19,10 +19,14 @@ dontDeleteFiles=Don't Delete Files pm_title=Manage User Profiles ps_title=Select User Profile +intro_start=To access your personal profile, which contains your stored messages, settings and other personalized information, please choose your profile from the list, and click %S to begin your session. +intro_switch=To switch to another profile, which contains stored messages, settings and other personalized information, please choose that profile from the list, and click %S to begin using that profile. + pm_button=Back... ps_button=Manage Profiles... -startButton=Start %brandShortName% +selectButton=Use Profile +startButton=Start %S exitButton=Exit cancel=Cancel diff --git a/mozilla/profile/resources/locale/en-US/profileSelection.dtd b/mozilla/profile/resources/locale/en-US/profileSelection.dtd index 66c8d5e3664..a2be423075c 100644 --- a/mozilla/profile/resources/locale/en-US/profileSelection.dtd +++ b/mozilla/profile/resources/locale/en-US/profileSelection.dtd @@ -28,9 +28,6 @@ - - - @@ -57,3 +54,6 @@ + + + diff --git a/mozilla/profile/src/Makefile.in b/mozilla/profile/src/Makefile.in index 2ecfa07ba36..03dc40e96b6 100644 --- a/mozilla/profile/src/Makefile.in +++ b/mozilla/profile/src/Makefile.in @@ -34,6 +34,8 @@ REQUIRES = xpcom \ docshell \ webbrwsr \ dom \ + js \ + xpconnect \ widget \ necko \ uriloader \ diff --git a/mozilla/profile/src/nsProfile.cpp b/mozilla/profile/src/nsProfile.cpp index 175ddc428d2..1ec10918951 100644 --- a/mozilla/profile/src/nsProfile.cpp +++ b/mozilla/profile/src/nsProfile.cpp @@ -91,6 +91,8 @@ #include "nsIDialogParamBlock.h" #include "nsIDOMWindowInternal.h" #include "nsIWindowWatcher.h" +#include "jsapi.h" +#include "nsIJSContextStack.h" #if defined (XP_UNIX) #elif defined (XP_MAC) @@ -450,7 +452,6 @@ nsProfile::LoadDefaultProfileDir(nsCString & profileURLStr, PRBool canInteract) nsCOMPtr prefBranch; nsCOMPtr profileURL; PRInt32 numProfiles=0; - nsXPIDLString currentProfileStr; nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; @@ -461,6 +462,15 @@ nsProfile::LoadDefaultProfileDir(nsCString & profileURLStr, PRBool canInteract) if (profileURLStr.Length() == 0) { + // If this flag is TRUE, it makes the multiple profile case + // just like the single profile case - the profile will be + // set to that returned by GetCurrentProfile(). It will prevent + // the profile selection dialog from being shown when we have + // multiple profiles. + + PRBool startWithLastUsedProfile = PR_FALSE; + GetStartWithLastUsedProfile(&startWithLastUsedProfile); + // This means that there was no command-line argument to force // profile UI to come up. But we need the UI anyway if there // are no profiles yet, or if there is more than one. @@ -470,7 +480,7 @@ nsProfile::LoadDefaultProfileDir(nsCString & profileURLStr, PRBool canInteract) if (NS_FAILED(rv)) return rv; // Will get set in call to SetCurrentProfile() below } - else if (numProfiles == 1) + else if (numProfiles == 1 || startWithLastUsedProfile) { // If we get here and the 1 profile is the current profile, // which can happen with QuickLaunch, there's no need to do @@ -507,13 +517,16 @@ nsProfile::LoadDefaultProfileDir(nsCString & profileURLStr, PRBool canInteract) nsCOMPtr windowWatcher(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; - - // We need to send a param to OpenWindow if the window is to be considered - // a dialog. It needs to be for script security reasons. This param block - // will be made use of soon. See bug 66833. + nsCOMPtr ioParamBlock(do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; - + + // String0 -> mode + // Int0 <- result code (1 == OK, 0 == Cancel) + + ioParamBlock->SetNumberStrings(1); + ioParamBlock->SetString(0, NS_LITERAL_STRING("startup").get()); + nsCOMPtr newWindow; rv = windowWatcher->OpenWindow(nsnull, profileURLStr.get(), @@ -522,15 +535,14 @@ nsProfile::LoadDefaultProfileDir(nsCString & profileURLStr, PRBool canInteract) ioParamBlock, getter_AddRefs(newWindow)); if (NS_FAILED(rv)) return rv; + PRInt32 dialogConfirmed; + ioParamBlock->GetInt(0, &dialogConfirmed); + if (dialogConfirmed == 0) return NS_ERROR_ABORT; } - // if we get here, and we don't have a current profile, - // return a failure so we will exit - // this can happen, if the user hits Exit in the profile manager dialog + nsXPIDLString currentProfileStr; rv = GetCurrentProfile(getter_Copies(currentProfileStr)); - if (NS_FAILED(rv) || (*(const PRUnichar*)currentProfileStr == 0)) { - return NS_ERROR_FAILURE; - } + if (NS_FAILED(rv)) return rv; // if at this point we have a current profile but it is not set, set it if (!mCurrentProfileAvailable) { @@ -1098,6 +1110,16 @@ NS_IMETHODIMP nsProfile::GetFirstProfile(PRUnichar **profileName) return NS_OK; } +NS_IMETHODIMP nsProfile::GetStartWithLastUsedProfile(PRBool *aStartWithLastUsedProfile) +{ + NS_ENSURE_ARG_POINTER(aStartWithLastUsedProfile); + return gProfileDataAccess->GetStartWithLastUsedProfile(aStartWithLastUsedProfile); +} + +NS_IMETHODIMP nsProfile::SetStartWithLastUsedProfile(PRBool aStartWithLastUsedProfile) +{ + return gProfileDataAccess->SetStartWithLastUsedProfile(aStartWithLastUsedProfile); +} // Returns the name of the current profile i.e., the last used profile NS_IMETHODIMP @@ -1185,6 +1207,18 @@ nsProfile::SetCurrentProfile(const PRUnichar * aCurrentProfile) return NS_OK; } + // Phase 2c: Now that things are torn down, force JS GC so that things which depend on + // resources which are about to go away in "profile-before-change" are destroyed first. + nsCOMPtr stack = + do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv); + if (NS_SUCCEEDED(rv)) + { + JSContext *cx = nsnull; + stack->GetSafeJSContext(&cx); + if (cx) + ::JS_GC(cx); + } + // Phase 3: Notify observers of a profile change observerService->NotifyObservers(subject, "profile-before-change", context.get()); @@ -1216,7 +1250,7 @@ nsProfile::SetCurrentProfile(const PRUnichar * aCurrentProfile) observerService->NotifyObservers(subject, "profile-change-net-restore", context.get()); mShutdownProfileToreDownNetwork = PR_FALSE; } -+ + // Phase 4: Notify observers that the profile has changed - Here they respond to new profile observerService->NotifyObservers(subject, "profile-do-change", context.get()); @@ -1226,6 +1260,9 @@ nsProfile::SetCurrentProfile(const PRUnichar * aCurrentProfile) // Now that a profile is established, set the profile defaults dir for the locale of this profile rv = DefineLocaleDefaultsDir(); NS_ASSERTION(NS_SUCCEEDED(rv), "nsProfile::DefineLocaleDefaultsDir failed"); + + // Phase 6: One last notification after the new profile is established + observerService->NotifyObservers(subject, "profile-initial-state", context.get()); return NS_OK; } @@ -1277,6 +1314,18 @@ NS_IMETHODIMP nsProfile::ShutDownCurrentProfile(PRUint32 shutDownType) // Phase 2b: Send the "teardown" notification observerService->NotifyObservers(subject, "profile-change-teardown", context.get()); + + // Phase 2c: Now that things are torn down, force JS GC so that things which depend on + // resources which are about to go away in "profile-before-change" are destroyed first. + nsCOMPtr stack = + do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv); + if (NS_SUCCEEDED(rv)) + { + JSContext *cx = nsnull; + stack->GetSafeJSContext(&cx); + if (cx) + ::JS_GC(cx); + } // Phase 3: Notify observers of a profile change observerService->NotifyObservers(subject, "profile-before-change", context.get()); @@ -1910,30 +1959,6 @@ nsresult nsProfile::Update4xProfileInfo() return rv; } -// launch the application with a profile of user's choice -// Prefs and FileLocation services are used here. -// FileLocation service to make ir forget about the global profile dir it had. -// Prefs service to kick off the startup to start the app with new profile's prefs. -NS_IMETHODIMP nsProfile::StartApprunner(const PRUnichar* profileName) -{ - NS_ENSURE_ARG_POINTER(profileName); - - nsresult rv = NS_OK; - -#if defined(DEBUG_profile) - { - printf("ProfileManager : StartApprunner\n"); - - printf("profileName passed in: %s\n", NS_LossyConvertUCS2toASCII(profileName).get()); - } -#endif - - rv = SetCurrentProfile(profileName); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to set profile"); - - return rv; -} - nsresult nsProfile::LoadNewProfilePrefs() { nsresult rv; diff --git a/mozilla/profile/src/nsProfileAccess.cpp b/mozilla/profile/src/nsProfileAccess.cpp index 1e13fb61f91..5d5a120dac1 100644 --- a/mozilla/profile/src/nsProfileAccess.cpp +++ b/mozilla/profile/src/nsProfileAccess.cpp @@ -100,6 +100,7 @@ static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CI #define kRegistryVersionString (NS_LITERAL_STRING("Version")) #define kRegistryVersion_1_0 (NS_LITERAL_STRING("1.0")) #define kRegistryCurrentVersion (NS_LITERAL_STRING("1.0")) +#define kRegistryStartWithLastString (NS_LITERAL_CSTRING("AutoStartWithLast")) // ********************************************************************** // class nsProfileAccess @@ -114,6 +115,7 @@ nsProfileAccess::nsProfileAccess() mProfileDataChanged = PR_FALSE; mForgetProfileCalled = PR_FALSE; m4xProfilesAdded = PR_FALSE; + mStartWithLastProfile = PR_FALSE; mProfiles = new nsVoidArray(); // Get the profile registry path @@ -352,6 +354,14 @@ nsProfileAccess::FillProfileInfo(nsIFile* regName) mHavePREGInfo = kRegistryNoString; mProfileDataChanged = PR_TRUE; } + + // Get the StartWithLastProfile flag + PRInt32 tempLong; + rv = registry->GetInt(profilesTreeKey, + kRegistryStartWithLastString.get(), + &tempLong); + if (NS_SUCCEEDED(rv)) + mStartWithLastProfile = tempLong; rv = registry->EnumerateSubtrees( profilesTreeKey, getter_AddRefs(enumKeys)); if (NS_FAILED(rv)) return rv; @@ -693,6 +703,12 @@ nsProfileAccess::UpdateRegistry(nsIFile* regName) mHavePREGInfo.get()); if (NS_FAILED(rv)) return rv; + // Set the StartWithLastProfile flag + rv = registry->SetInt(profilesTreeKey, + kRegistryStartWithLastString.get(), + mStartWithLastProfile); + if (NS_FAILED(rv)) return rv; + rv = registry->EnumerateSubtrees(profilesTreeKey, getter_AddRefs(enumKeys)); if (NS_FAILED(rv)) return rv; @@ -918,6 +934,22 @@ nsProfileAccess::SetProfileLastModTime(const PRUnichar *profileName, PRInt64 las return NS_ERROR_FAILURE; } +nsresult +nsProfileAccess::GetStartWithLastUsedProfile(PRBool *aStartWithLastUsedProfile) +{ + NS_ENSURE_ARG_POINTER(aStartWithLastUsedProfile); + *aStartWithLastUsedProfile = mStartWithLastProfile; + return NS_OK; +} + +nsresult +nsProfileAccess::SetStartWithLastUsedProfile(PRBool aStartWithLastUsedProfile) +{ + mStartWithLastProfile = aStartWithLastUsedProfile; + mProfileDataChanged = PR_TRUE; + return NS_OK; +} + // Return the list of profiles, 4x, 5x, or both. nsresult nsProfileAccess::GetProfileList(PRInt32 whichKind, PRUint32 *length, PRUnichar ***result) diff --git a/mozilla/profile/src/nsProfileAccess.h b/mozilla/profile/src/nsProfileAccess.h index 8650f01e209..08489ef7801 100644 --- a/mozilla/profile/src/nsProfileAccess.h +++ b/mozilla/profile/src/nsProfileAccess.h @@ -121,7 +121,7 @@ private: nsString mCurrentProfile; nsString mHavePREGInfo; PRBool m4xProfilesAdded; - + PRBool mStartWithLastProfile; public: PRBool mProfileDataChanged; PRBool mForgetProfileCalled; @@ -138,7 +138,9 @@ public: nsresult GetOriginalProfileDir(const PRUnichar *profileName, nsILocalFile **orginalDir); nsresult SetMigratedFromDir(const PRUnichar *profileName, nsILocalFile *orginalDir); nsresult SetProfileLastModTime(const PRUnichar *profileName, PRInt64 lastModTime); - + nsresult GetStartWithLastUsedProfile(PRBool *aStartWithLastUsedProfile); + nsresult SetStartWithLastUsedProfile(PRBool aStartWithLastUsedProfile); + // if fromImport is true all the 4.x profiles will be added to mProfiles with the isImportType flag set. // pass fromImport as True only if you are calling from the Import Module. nsresult Get4xProfileInfo(const char *registryName, PRBool fromImport); diff --git a/mozilla/xpfe/appshell/public/Makefile.in b/mozilla/xpfe/appshell/public/Makefile.in index 4aee6230dd1..9a0c0f1bab6 100644 --- a/mozilla/xpfe/appshell/public/Makefile.in +++ b/mozilla/xpfe/appshell/public/Makefile.in @@ -47,6 +47,7 @@ XPIDLSRCS = \ nsITimingService.idl \ nsINativeAppSupport.idl \ nsIPopupWindowManager.idl \ + nsICloseAllWindows.idl \ $(NULL) ifeq ($(MOZ_WIDGET_TOOLKIT),windows) diff --git a/mozilla/xpfe/appshell/public/nsIAppShellService.idl b/mozilla/xpfe/appshell/public/nsIAppShellService.idl index d3a70bc816b..b60fa83486c 100644 --- a/mozilla/xpfe/appshell/public/nsIAppShellService.idl +++ b/mozilla/xpfe/appshell/public/nsIAppShellService.idl @@ -200,5 +200,22 @@ interface nsIAppShellService : nsISupports */ void enterLastWindowClosingSurvivalArea(); void exitLastWindowClosingSurvivalArea(); + + /** + * Creates the initial state of the application by launching tasks + * specfied by "general.startup.*" prefs. + * @param aWindowWidth the width to make the initial window(s) opened + * @param aWindowHeight the height to make the initial window(s) opened + * @note SIZE_TO_CONTENT may be used for width or height. + * @return TRUE if a window was opened + */ + boolean createStartupState(in long aWindowWidth, in long aWindowHeight); + + /** + * Ensures that at least one window exists after creating the startup state. + * If one has not been made, this will create a browser window. + * @param aCmdLineService the command line from which startup args can be read. + */ + void ensure1Window(in nsICmdLineService aCmdLineService); }; diff --git a/mozilla/xpfe/appshell/src/Makefile.in b/mozilla/xpfe/appshell/src/Makefile.in index f5169cd8f88..66de0e622fa 100644 --- a/mozilla/xpfe/appshell/src/Makefile.in +++ b/mozilla/xpfe/appshell/src/Makefile.in @@ -58,6 +58,7 @@ REQUIRES = xpcom \ profile \ unicharutil \ embed_base \ + uconv \ exthandler \ $(NULL) @@ -94,6 +95,8 @@ endif endif endif +EXTRA_COMPONENTS = nsCloseAllWindows.js + ifeq ($(OS_ARCH),WINNT) EXTRA_DSO_LIBS = gkgfx endif diff --git a/mozilla/xpfe/appshell/src/nsAppShellService.cpp b/mozilla/xpfe/appshell/src/nsAppShellService.cpp index 376b4d402fc..7c859c8c2d4 100644 --- a/mozilla/xpfe/appshell/src/nsAppShellService.cpp +++ b/mozilla/xpfe/appshell/src/nsAppShellService.cpp @@ -64,9 +64,7 @@ #include "nsICmdLineService.h" #include "nsCRT.h" #include "nsITimelineService.h" -#ifdef NS_DEBUG #include "prprf.h" -#endif #if defined(XP_MAC) || defined(XP_MACOSX) #include @@ -89,6 +87,12 @@ static PRBool OnMacOSX(); #include "nsAppShellService.h" #include "nsIProfileInternal.h" +#include "nsIProfileChangeStatus.h" +#include "nsICloseAllWindows.h" +#include "nsISupportsPrimitives.h" +#include "nsIPlatformCharset.h" +#include "nsICharsetConverterManager.h" +#include "nsIUnicodeDecoder.h" /* Define Class IDs */ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); @@ -96,11 +100,16 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); static NS_DEFINE_CID(kXPConnectCID, NS_XPCONNECT_CID); -#define gEQActivatedNotification "nsIEventQueueActivated" -#define gEQDestroyedNotification "nsIEventQueueDestroyed" -#define gSkinSelectedTopic "skin-selected" -#define gLocaleSelectedTopic "locale-selected" -#define gInstallRestartTopic "xpinstall-restart" +#define gEQActivatedNotification "nsIEventQueueActivated" +#define gEQDestroyedNotification "nsIEventQueueDestroyed" +#define gSkinSelectedTopic "skin-selected" +#define gLocaleSelectedTopic "locale-selected" +#define gInstallRestartTopic "xpinstall-restart" +#define gProfileChangeTeardownTopic "profile-change-teardown" +#define gProfileInitialStateTopic "profile-initial-state" + +// Static Function Prototypes +static nsresult ConvertToUnicode(nsString& aCharset, const char* inString, nsAString& outString); nsAppShellService::nsAppShellService() : mDeleteCalled(PR_FALSE), @@ -1048,6 +1057,254 @@ nsAppShellService::ExitLastWindowClosingSurvivalArea(void) return NS_OK; } +//------------------------------------------------------------------------- + +NS_IMETHODIMP +nsAppShellService::CreateStartupState(PRInt32 aWindowWidth, PRInt32 aWindowHeight, PRBool *_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + nsresult rv; + + nsCOMPtr prefService(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (!prefService) + return NS_ERROR_FAILURE; + nsCOMPtr startupBranch; + prefService->GetBranch(PREF_STARTUP_PREFIX, getter_AddRefs(startupBranch)); + if (!startupBranch) + return NS_ERROR_FAILURE; + + PRUint32 childCount; + char **childArray = nsnull; + rv = startupBranch->GetChildList("", &childCount, &childArray); + if (NS_FAILED(rv)) + return rv; + + for (PRUint32 i = 0; i < childCount; i++) { + PRBool prefValue; + startupBranch->GetBoolPref(childArray[i], &prefValue); + if (prefValue) { + PRBool windowOpened; + rv = LaunchTask(childArray[i], aWindowHeight, aWindowWidth, &windowOpened); + if (NS_SUCCEEDED(rv) && windowOpened) + *_retval = PR_TRUE; + } + } + + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray); + + return NS_OK; +} + +nsresult +nsAppShellService::LaunchTask(const char *aParam, PRInt32 height, PRInt32 width, PRBool *windowOpened) +{ + nsresult rv = NS_OK; + + nsCOMPtr cmdLine = + do_GetService("@mozilla.org/appshell/commandLineService;1", &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr handler; + rv = cmdLine->GetHandlerForParam(aParam, getter_AddRefs(handler)); + if (NS_FAILED(rv)) return rv; + + nsXPIDLCString chromeUrlForTask; + rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask)); + if (NS_FAILED(rv)) return rv; + + PRBool handlesArgs = PR_FALSE; + rv = handler->GetHandlesArgs(&handlesArgs); + if (handlesArgs) { + nsXPIDLString defaultArgs; + rv = handler->GetDefaultArgs(getter_Copies(defaultArgs)); + if (NS_FAILED(rv)) return rv; + rv = OpenWindow(chromeUrlForTask, defaultArgs, SIZE_TO_CONTENT, SIZE_TO_CONTENT); + } + else { + rv = OpenWindow(chromeUrlForTask, nsString(), width, height); + } + + // If we get here without an error, then a window was opened OK. + if (NS_SUCCEEDED(rv)) { + *windowOpened = PR_TRUE; + } + + return rv; +} + +nsresult +nsAppShellService::OpenWindow(const nsAFlatCString& aChromeURL, + const nsAFlatString& aAppArgs, + PRInt32 aWidth, PRInt32 aHeight) +{ + nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); + nsCOMPtr sarg(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); + if (!wwatch || !sarg) + return NS_ERROR_FAILURE; + + // Make sure a profile is selected. + + // We need the native app support object. If this fails, we still proceed. + // That's because some platforms don't have a native app + // support implementation. On those platforms, "ensuring a + // profile" is moot (because they don't support "-turbo", + // basically). Specifically, because they don't do turbo, they will + // *always* have a profile selected. + nsCOMPtr nativeApp; + if (NS_SUCCEEDED(GetNativeAppSupport(getter_AddRefs(nativeApp)))) + { + nsCOMPtr cmdLine = + do_GetService("@mozilla.org/appshell/commandLineService;1"); + + if (cmdLine) { + // Make sure profile has been selected. + // At this point, we have to look for failure. That + // handles the case where the user chooses "Exit" on + // the profile manager window. + if (NS_FAILED(nativeApp->EnsureProfile(cmdLine))) + return NS_ERROR_NOT_INITIALIZED; + } + } + + sarg->SetData(aAppArgs); + + nsCAutoString features("chrome,dialog=no,all"); + if (aHeight != nsIAppShellService::SIZE_TO_CONTENT) { + features.Append(",height="); + features.AppendInt(aHeight); + } + if (aWidth != nsIAppShellService::SIZE_TO_CONTENT) { + features.Append(",width="); + features.AppendInt(aWidth); + } + + nsCOMPtr newWindow; + return wwatch->OpenWindow(0, aChromeURL.get(), "_blank", + features.get(), sarg, + getter_AddRefs(newWindow)); +} + +NS_IMETHODIMP +nsAppShellService::Ensure1Window(nsICmdLineService *aCmdLineService) +{ + nsresult rv; + + // If starting up in server mode, then we do things differently. + nsCOMPtr nativeApp; + rv = GetNativeAppSupport(getter_AddRefs(nativeApp)); + if (NS_SUCCEEDED(rv)) { + PRBool isServerMode = PR_FALSE; + nativeApp->GetIsServerMode(&isServerMode); + if (isServerMode) { + nativeApp->StartServerMode(); + } + PRBool shouldShowUI = PR_TRUE; + nativeApp->GetShouldShowUI(&shouldShowUI); + if (!shouldShowUI) { + return NS_OK; + } + } + + nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID, &rv)); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr windowEnumerator; + if (NS_SUCCEEDED(windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator)))) + { + PRBool more; + windowEnumerator->HasMoreElements(&more); + if (!more) + { + // No window exists so lets create a browser one + PRInt32 height = nsIAppShellService::SIZE_TO_CONTENT; + PRInt32 width = nsIAppShellService::SIZE_TO_CONTENT; + + // Get the value of -width option + nsXPIDLCString tempString; + rv = aCmdLineService->GetCmdLineValue("-width", getter_Copies(tempString)); + if (NS_SUCCEEDED(rv) && !tempString.IsEmpty()) + PR_sscanf(tempString.get(), "%d", &width); + + + // Get the value of -height option + rv = aCmdLineService->GetCmdLineValue("-height", getter_Copies(tempString)); + if (NS_SUCCEEDED(rv) && !tempString.IsEmpty()) + PR_sscanf(tempString.get(), "%d", &height); + + rv = OpenBrowserWindow(height, width); + } + } + return rv; +} + +nsresult +nsAppShellService::OpenBrowserWindow(PRInt32 height, PRInt32 width) +{ + nsresult rv; + nsCOMPtr handler(do_GetService("@mozilla.org/commandlinehandler/general-startup;1?type=browser", &rv)); + if (NS_FAILED(rv)) return rv; + + nsXPIDLCString chromeUrlForTask; + rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr cmdLine = do_GetService("@mozilla.org/appshell/commandLineService;1", &rv); + if (NS_FAILED(rv)) return rv; + + nsXPIDLCString urlToLoad; + rv = cmdLine->GetURLToLoad(getter_Copies(urlToLoad)); + if (NS_FAILED(rv)) return rv; + + if (!urlToLoad.IsEmpty()) { + +#ifdef DEBUG_CMD_LINE + printf("url to load: %s\n", urlToLoad.get()); +#endif /* DEBUG_CMD_LINE */ + + nsAutoString url; + if (nsCRT::IsAscii(urlToLoad)) { + url.AssignWithConversion(urlToLoad); + } + else { + // get a platform charset + nsAutoString charSet; + nsCOMPtr platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv)); + if (NS_FAILED(rv)) { + NS_ASSERTION(0, "Failed to get a platform charset"); + return rv; + } + + rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charSet); + if (NS_FAILED(rv)) { + NS_ASSERTION(0, "Failed to get a charset"); + return rv; + } + + // convert the cmdLine URL to Unicode + rv = ConvertToUnicode(charSet, urlToLoad, url); + if (NS_FAILED(rv)) { + NS_ASSERTION(0, "Failed to convert commandline url to unicode"); + return rv; + } + } + rv = OpenWindow(chromeUrlForTask, url, width, height); + + } else { + + nsXPIDLString defaultArgs; + rv = handler->GetDefaultArgs(getter_Copies(defaultArgs)); + if (NS_FAILED(rv)) return rv; + +#ifdef DEBUG_CMD_LINE + printf("default args: %s\n", NS_ConvertUCS2toUTF8(defaultArgs).get()); +#endif /* DEBUG_CMD_LINE */ + + rv = OpenWindow(chromeUrlForTask, defaultArgs, width, height); + } + + return rv; +} //------------------------------------------------------------------------- // nsIObserver interface and friends @@ -1055,10 +1312,10 @@ nsAppShellService::ExitLastWindowClosingSurvivalArea(void) NS_IMETHODIMP nsAppShellService::Observe(nsISupports *aSubject, const char *aTopic, - const PRUnichar *) + const PRUnichar *aData) { NS_ASSERTION(mAppShell, "appshell service notified before appshell built"); - if (!nsCRT::strcmp(aTopic, gEQActivatedNotification) ) { + if (!strcmp(aTopic, gEQActivatedNotification)) { nsCOMPtr eq(do_QueryInterface(aSubject)); if (eq) { PRBool isNative = PR_TRUE; @@ -1067,7 +1324,7 @@ NS_IMETHODIMP nsAppShellService::Observe(nsISupports *aSubject, if (isNative) mAppShell->ListenToEventQueue(eq, PR_TRUE); } - } else if (!nsCRT::strcmp(aTopic, gEQDestroyedNotification)) { + } else if (!strcmp(aTopic, gEQDestroyedNotification)) { nsCOMPtr eq(do_QueryInterface(aSubject)); if (eq) { PRBool isNative = PR_TRUE; @@ -1076,11 +1333,35 @@ NS_IMETHODIMP nsAppShellService::Observe(nsISupports *aSubject, if (isNative) mAppShell->ListenToEventQueue(eq, PR_FALSE); } - } else if (!nsCRT::strcmp(aTopic, gSkinSelectedTopic) || - !nsCRT::strcmp(aTopic, gLocaleSelectedTopic) || - !nsCRT::strcmp(aTopic, gInstallRestartTopic)) { + } else if (!strcmp(aTopic, gSkinSelectedTopic) || + !strcmp(aTopic, gLocaleSelectedTopic) || + !strcmp(aTopic, gInstallRestartTopic)) { if (mNativeAppSupport) mNativeAppSupport->SetIsServerMode(PR_FALSE); + } else if (!strcmp(aTopic, gProfileChangeTeardownTopic)) { + nsresult rv; + EnterLastWindowClosingSurvivalArea(); + // NOTE: No early error exits because we need to execute the + // balancing ExitLastWindowClosingSurvivalArea(). + nsCOMPtr closer = + do_CreateInstance("@mozilla.org/appshell/closeallwindows;1", &rv); + NS_ASSERTION(closer, "Failed to create nsICloseAllWindows impl."); + PRBool proceedWithSwitch = PR_FALSE; + if (closer) + rv = closer->CloseAll(PR_TRUE, &proceedWithSwitch); + if (NS_FAILED(rv) || !proceedWithSwitch) { + nsCOMPtr changeStatus(do_QueryInterface(aSubject)); + if (changeStatus) + changeStatus->VetoChange(); + } + ExitLastWindowClosingSurvivalArea(); + } else if (!strcmp(aTopic, gProfileInitialStateTopic) && + nsDependentString(aData).Equals(NS_LITERAL_STRING("switch"))) { + // Now, establish the startup state according to the new prefs. + PRBool openedWindow; + CreateStartupState(SIZE_TO_CONTENT, SIZE_TO_CONTENT, &openedWindow); + if (!openedWindow) + OpenBrowserWindow(SIZE_TO_CONTENT, SIZE_TO_CONTENT); } return NS_OK; } @@ -1106,12 +1387,16 @@ void nsAppShellService::RegisterObserver(PRBool aRegister) os->AddObserver(weObserve, gSkinSelectedTopic, PR_TRUE); os->AddObserver(weObserve, gLocaleSelectedTopic, PR_TRUE); os->AddObserver(weObserve, gInstallRestartTopic, PR_TRUE); + os->AddObserver(weObserve, gProfileChangeTeardownTopic, PR_TRUE); + os->AddObserver(weObserve, gProfileInitialStateTopic, PR_TRUE); } else { os->RemoveObserver(weObserve, gEQActivatedNotification); os->RemoveObserver(weObserve, gEQDestroyedNotification); os->RemoveObserver(weObserve, gSkinSelectedTopic); os->RemoveObserver(weObserve, gLocaleSelectedTopic); os->RemoveObserver(weObserve, gInstallRestartTopic); + os->RemoveObserver(weObserve, gProfileChangeTeardownTopic); + os->RemoveObserver(weObserve, gProfileInitialStateTopic); } NS_RELEASE(glop); } @@ -1156,3 +1441,40 @@ OnMacOSX() return gOnMacOSX; } #endif + +static nsresult ConvertToUnicode(nsString& aCharset, const char* inString, nsAString& outString) +{ + nsresult rv; + + // convert result to unicode + nsCOMPtr ccm(do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID , &rv)); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr decoder; + rv = ccm->GetUnicodeDecoder(&aCharset, getter_AddRefs(decoder)); + if (NS_FAILED(rv)) + return rv; + + PRInt32 uniLength = 0; + PRInt32 srcLength = strlen(inString); + rv = decoder->GetMaxLength(inString, srcLength, &uniLength); + if (NS_FAILED(rv)) + return rv; + + PRUnichar *unichars = new PRUnichar [uniLength]; + if (nsnull != unichars) { + // convert to unicode + rv = decoder->Convert(inString, &srcLength, unichars, &uniLength); + if (NS_SUCCEEDED(rv)) { + // Pass back the unicode string + outString.Assign(unichars, uniLength); + } + delete [] unichars; + } + else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + + return rv; +} diff --git a/mozilla/xpfe/appshell/src/nsAppShellService.h b/mozilla/xpfe/appshell/src/nsAppShellService.h index e0ea4660a3a..28fe6d23444 100644 --- a/mozilla/xpfe/appshell/src/nsAppShellService.h +++ b/mozilla/xpfe/appshell/src/nsAppShellService.h @@ -100,6 +100,17 @@ protected: private: nsresult CheckAndRemigrateDefunctProfile(); + + nsresult LaunchTask(const char *aParam, + PRInt32 height, PRInt32 width, + PRBool *windowOpened); + + nsresult OpenWindow(const nsAFlatCString& aChromeURL, + const nsAFlatString& aAppArgs, + PRInt32 aWidth, PRInt32 aHeight); + + nsresult OpenBrowserWindow(PRInt32 height, PRInt32 width); + }; #endif diff --git a/mozilla/xpfe/bootstrap/nsAppRunner.cpp b/mozilla/xpfe/bootstrap/nsAppRunner.cpp index b120ef8c21a..a58f27b6e87 100644 --- a/mozilla/xpfe/bootstrap/nsAppRunner.cpp +++ b/mozilla/xpfe/bootstrap/nsAppRunner.cpp @@ -60,8 +60,6 @@ #include "nsIAppShellService.h" #include "nsIAppStartupNotifier.h" #include "nsIObserverService.h" -#include "nsIPlatformCharset.h" -#include "nsICharsetConverterManager.h" #include "nsAppShellCIDs.h" #include "prprf.h" #include "nsCRT.h" @@ -573,43 +571,6 @@ static void DumpArbitraryHelp() return; } -static -nsresult LaunchApplication(const char *aParam, PRInt32 height, PRInt32 width, PRBool *windowOpened) -{ - nsresult rv = NS_OK; - - nsCOMPtr cmdLine = - do_GetService("@mozilla.org/appshell/commandLineService;1", &rv); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr handler; - rv = cmdLine->GetHandlerForParam(aParam, getter_AddRefs(handler)); - if (NS_FAILED(rv)) return rv; - - nsXPIDLCString chromeUrlForTask; - rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask)); - if (NS_FAILED(rv)) return rv; - - PRBool handlesArgs = PR_FALSE; - rv = handler->GetHandlesArgs(&handlesArgs); - if (handlesArgs) { - nsXPIDLString defaultArgs; - rv = handler->GetDefaultArgs(getter_Copies(defaultArgs)); - if (NS_FAILED(rv)) return rv; - rv = OpenWindow(chromeUrlForTask, defaultArgs); - } - else { - rv = OpenWindow(chromeUrlForTask, width, height); - } - - // If we get here without an error, then a window was opened OK. - if (NS_SUCCEEDED(rv)) { - *windowOpened = PR_TRUE; - } - - return rv; -} - static nsresult LaunchApplicationWithArgs(const char *commandLineArg, nsICmdLineService *cmdLineArgs, @@ -708,52 +669,6 @@ LaunchApplicationWithArgs(const char *commandLineArg, return NS_OK; } -typedef struct -{ - nsIPref *prefs; - PRInt32 height; - PRInt32 width; - PRBool windowOpened; -} StartupClosure; - -static -void startupPrefEnumerationFunction(const char *prefName, void *data) -{ - nsresult rv; - PRBool prefValue = PR_FALSE; - - if (!data || !prefName) return; - - StartupClosure *closure = (StartupClosure *)data; - -#ifdef DEBUG_CMD_LINE - printf("getting %s\n", prefName); -#endif /* DEBUG_CMD_LINE */ - - rv = closure->prefs->GetBoolPref(prefName, &prefValue); - if (NS_FAILED(rv)) return; - -#ifdef DEBUG_CMD_LINE - printf("%s = %d\n", prefName, prefValue); -#endif /* DEBUG_CMD_LINE */ - - PRUint32 prefixLen = PL_strlen(PREF_STARTUP_PREFIX); - - // if the pref is "general.startup.", ignore it. - if (PL_strlen(prefName) <= prefixLen) return; - - if (prefValue) { - // skip past the "general.startup." part of the string - const char *param = prefName + prefixLen; - -#ifdef DEBUG_CMD_LINE - printf("cmd line parameter = %s\n", param); -#endif /* DEBUG_CMD_LINE */ - rv = LaunchApplication(param, closure->height, closure->width, &closure->windowOpened); - } - return; -} - static PRBool IsStartupCommand(const char *arg) { if (!arg) return PR_FALSE; @@ -772,38 +687,34 @@ static PRBool IsStartupCommand(const char *arg) return PR_FALSE; } -static nsresult HandleArbitraryStartup(nsICmdLineService* cmdLineArgs, nsIPref *prefs, PRBool heedGeneralStartupPrefs, PRBool *windowOpened) + +// This should be done by app shell enumeration someday +nsresult DoCommandLines(nsICmdLineService* cmdLineArgs, PRBool heedGeneralStartupPrefs, PRBool *windowOpened) { - nsresult rv; + NS_ENSURE_ARG(windowOpened); + *windowOpened = PR_FALSE; + + nsresult rv; + PRInt32 height = nsIAppShellService::SIZE_TO_CONTENT; PRInt32 width = nsIAppShellService::SIZE_TO_CONTENT; nsXPIDLCString tempString; // Get the value of -width option rv = cmdLineArgs->GetCmdLineValue("-width", getter_Copies(tempString)); - if (NS_FAILED(rv)) return rv; - - if ((const char*)tempString) PR_sscanf(tempString, "%d", &width); + if (NS_SUCCEEDED(rv) && !tempString.IsEmpty()) + PR_sscanf(tempString.get(), "%d", &width); // Get the value of -height option rv = cmdLineArgs->GetCmdLineValue("-height", getter_Copies(tempString)); - if (NS_FAILED(rv)) return rv; - - if ((const char*)tempString) PR_sscanf(tempString, "%d", &height); - + if (NS_SUCCEEDED(rv) && !tempString.IsEmpty()) + PR_sscanf(tempString.get(), "%d", &height); + if (heedGeneralStartupPrefs) { -#ifdef DEBUG_CMD_LINE - printf("XXX iterate over all the general.startup.* prefs\n"); -#endif /* DEBUG_CMD_LINE */ - StartupClosure closure; - - closure.prefs = prefs; - closure.height = height; - closure.width = width; - closure.windowOpened = *windowOpened; - - prefs->EnumerateChildren(PREF_STARTUP_PREFIX, startupPrefEnumerationFunction,(void *)(&closure)); - *windowOpened = closure.windowOpened; + nsCOMPtr appShell(do_GetService("@mozilla.org/appshell/appShellService;1", &rv)); + if (NS_FAILED(rv)) return rv; + rv = appShell->CreateStartupState(width, height, windowOpened); + if (NS_FAILED(rv)) return rv; } else { PRInt32 argc = 0; @@ -834,31 +745,14 @@ static nsresult HandleArbitraryStartup(nsICmdLineService* cmdLineArgs, nsIPref * rv = LaunchApplicationWithArgs((const char *)(argv[i]), cmdLineArgs, command, height, width, windowOpened); - if (rv == NS_ERROR_NOT_AVAILABLE || rv == NS_ERROR_ABORT) { + if (rv == NS_ERROR_NOT_AVAILABLE || rv == NS_ERROR_ABORT) return rv; - } } } } - return NS_OK; } -// This should be done by app shell enumeration someday -nsresult DoCommandLines(nsICmdLineService* cmdLine, PRBool heedGeneralStartupPrefs, PRBool *windowOpened) -{ - NS_ENSURE_ARG(windowOpened); - *windowOpened = PR_FALSE; - - nsresult rv; - - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID, &rv)); - if (NS_FAILED(rv)) return rv; - - rv = HandleArbitraryStartup(cmdLine, prefs, heedGeneralStartupPrefs, windowOpened); - return rv; -} - static nsresult DoOnShutdown() { nsresult rv; @@ -897,180 +791,6 @@ static nsresult DoOnShutdown() return rv; } -static nsresult ConvertToUnicode(nsString& aCharset, const char* inString, nsAString& outString) -{ - nsresult rv; - - // convert result to unicode - nsCOMPtr ccm(do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID , &rv)); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr decoder; - rv = ccm->GetUnicodeDecoder(&aCharset, getter_AddRefs(decoder)); - if (NS_FAILED(rv)) - return rv; - - PRInt32 uniLength = 0; - PRInt32 srcLength = strlen(inString); - rv = decoder->GetMaxLength(inString, srcLength, &uniLength); - if (NS_FAILED(rv)) - return rv; - - PRUnichar *unichars = new PRUnichar [uniLength]; - if (nsnull != unichars) { - // convert to unicode - rv = decoder->Convert(inString, &srcLength, unichars, &uniLength); - if (NS_SUCCEEDED(rv)) { - // Pass back the unicode string - outString.Assign(unichars, uniLength); - } - delete [] unichars; - } - else { - rv = NS_ERROR_OUT_OF_MEMORY; - } - - return rv; -} -static PRBool IsAscii(const char *aString) { - while(*aString) { - if( 0x80 & *aString) - return PR_FALSE; - aString++; - } - return PR_TRUE; -} - -static nsresult OpenBrowserWindow(PRInt32 height, PRInt32 width) -{ - nsresult rv; - nsCOMPtr handler(do_GetService("@mozilla.org/commandlinehandler/general-startup;1?type=browser", &rv)); - if (NS_FAILED(rv)) return rv; - - nsXPIDLCString chromeUrlForTask; - rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask)); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr cmdLine = do_GetService("@mozilla.org/appshell/commandLineService;1", &rv); - if (NS_FAILED(rv)) return rv; - - nsXPIDLCString urlToLoad; - rv = cmdLine->GetURLToLoad(getter_Copies(urlToLoad)); - if (NS_FAILED(rv)) return rv; - - if (!urlToLoad.IsEmpty()) { - -#ifdef DEBUG_CMD_LINE - printf("url to load: %s\n", urlToLoad.get()); -#endif /* DEBUG_CMD_LINE */ - - nsAutoString url; - if (IsAscii(urlToLoad)) { - url.AssignWithConversion(urlToLoad); - } - else { - // get a platform charset - nsAutoString charSet; - nsCOMPtr platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv)); - if (NS_FAILED(rv)) { - NS_ASSERTION(0, "Failed to get a platform charset"); - return rv; - } - - rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charSet); - if (NS_FAILED(rv)) { - NS_ASSERTION(0, "Failed to get a charset"); - return rv; - } - - // convert the cmdLine URL to Unicode - rv = ConvertToUnicode(charSet, urlToLoad, url); - if (NS_FAILED(rv)) { - NS_ASSERTION(0, "Failed to convert commandline url to unicode"); - return rv; - } - } - rv = OpenWindow(chromeUrlForTask, url, width, height); - - } else { - - nsXPIDLString defaultArgs; - rv = handler->GetDefaultArgs(getter_Copies(defaultArgs)); - if (NS_FAILED(rv)) return rv; - -#ifdef DEBUG_CMD_LINE - printf("default args: %s\n", NS_ConvertUCS2toUTF8(defaultArgs).get()); -#endif /* DEBUG_CMD_LINE */ - - rv = OpenWindow(chromeUrlForTask, defaultArgs, width, height); - } - - return rv; -} - - -static nsresult Ensure1Window(nsICmdLineService* cmdLineArgs) -{ - nsresult rv; - - // If starting up in server mode, then we do things differently. - nsCOMPtr nativeApp; - rv = GetNativeAppSupport(getter_AddRefs(nativeApp)); - if (NS_SUCCEEDED(rv)) { - PRBool isServerMode = PR_FALSE; - nativeApp->GetIsServerMode(&isServerMode); - if (isServerMode) { - nativeApp->StartServerMode(); - } - PRBool shouldShowUI = PR_TRUE; - nativeApp->GetShouldShowUI(&shouldShowUI); - if (!shouldShowUI) { - return NS_OK; - } - } - - nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID, &rv)); - - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr windowEnumerator; - - if (NS_SUCCEEDED(windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator)))) - { - PRBool more; - - windowEnumerator->HasMoreElements(&more); - if (!more) - { - // No window exists so lets create a browser one - PRInt32 height = nsIAppShellService::SIZE_TO_CONTENT; - PRInt32 width = nsIAppShellService::SIZE_TO_CONTENT; - - // Get the value of -width option - nsXPIDLCString tempString; - rv = cmdLineArgs->GetCmdLineValue("-width", getter_Copies(tempString)); - if (NS_FAILED(rv)) - return rv; - if ((const char*)tempString) - PR_sscanf(tempString, "%d", &width); - - - // Get the value of -height option - rv = cmdLineArgs->GetCmdLineValue("-height", getter_Copies(tempString)); - if (NS_FAILED(rv)) - return rv; - - if ((const char*)tempString) - PR_sscanf(tempString, "%d", &height); - - rv = OpenBrowserWindow(height, width); - } - } - return rv; -} - // match OS locale static char kMatchOSLocalePref[] = "intl.locale.matchOS"; @@ -1466,8 +1186,6 @@ static nsresult main1(int argc, char* argv[], nsISupports *nativeApp ) NS_TIMELINE_LEAVE("InitializeProfileService"); if (NS_FAILED(rv)) return rv; - // rjc: now must explicitly call appshell's CreateHiddenWindow() function AFTER profile manager. - // if the profile manager ever switches to using nsIDOMWindowInternal stuff, this might have to change NS_TIMELINE_ENTER("appShell->CreateHiddenWindow"); appShell->CreateHiddenWindow(); NS_TIMELINE_LEAVE("appShell->CreateHiddenWindow"); @@ -1517,7 +1235,7 @@ static nsresult main1(int argc, char* argv[], nsISupports *nativeApp ) // Make sure there exists at least 1 window. NS_TIMELINE_ENTER("Ensure1Window"); - rv = Ensure1Window(cmdLineArgs); + rv = appShell->Ensure1Window(cmdLineArgs); NS_TIMELINE_LEAVE("Ensure1Window"); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to Ensure1Window"); if (NS_FAILED(rv)) return rv; diff --git a/mozilla/xpfe/communicator/resources/content/tasksOverlay.js b/mozilla/xpfe/communicator/resources/content/tasksOverlay.js index b2374a037c9..ee397c1ddea 100644 --- a/mozilla/xpfe/communicator/resources/content/tasksOverlay.js +++ b/mozilla/xpfe/communicator/resources/content/tasksOverlay.js @@ -204,4 +204,22 @@ function checkFocusedWindow() } } +function toProfileManager() +{ + var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] + .getService(Components.interfaces.nsIWindowWatcher); + var params = Components.classes["@mozilla.org/embedcomp/dialogparam;1"] + .createInstance(Components.interfaces.nsIDialogParamBlock); + + params.SetNumberStrings(1); + params.SetString(0, "menu"); + ww.openWindow(null, // no parent + "chrome://communicator/content/profile/profileSelection.xul", + null, + "centerscreen,chrome,modal,titlebar", + params); + + // Here, we don't care about the result code + // that was returned in the param block. +} diff --git a/mozilla/xpfe/communicator/resources/content/tasksOverlay.xul b/mozilla/xpfe/communicator/resources/content/tasksOverlay.xul index af108e92ec5..4730df15f89 100644 --- a/mozilla/xpfe/communicator/resources/content/tasksOverlay.xul +++ b/mozilla/xpfe/communicator/resources/content/tasksOverlay.xul @@ -19,6 +19,7 @@ + @@ -36,6 +37,8 @@ + + diff --git a/mozilla/xpfe/communicator/resources/locale/en-US/tasksOverlay.dtd b/mozilla/xpfe/communicator/resources/locale/en-US/tasksOverlay.dtd index 5bd8945ff68..0756e0d9030 100644 --- a/mozilla/xpfe/communicator/resources/locale/en-US/tasksOverlay.dtd +++ b/mozilla/xpfe/communicator/resources/locale/en-US/tasksOverlay.dtd @@ -35,3 +35,7 @@ + + + +