Bug 81712; new turbo-mode implementation, removes old stuff and replaces it with code that no longer holds a browser window open; r=syd, sr=blake, a=asa

This commit is contained in:
law%netscape.com 2001-06-12 22:33:34 +00:00
parent a783e94b5e
commit 2350eb1a95
10 changed files with 154 additions and 147 deletions

View File

@ -121,11 +121,17 @@
* invoking the Hide() method on the nsISplashScreen
* interface maintained by the app shell service.
*
* cacheBrowserWindow - Takes an about-to-be-closed navigator window
* and "caches it" for later use. It returns an
* indicator of whether the window was actually
* cached. If that result is false, then the
* caller should close the window normally.
* startServerMode - Method that "starts" server mode. Typically, this
* will create a hidden Navigator window (and then close
* it) in order to fill the cache, load shared libraries,
* etc. Note that this method does not set the
* isServerMode attribute, nor does setting that attribute
* "start" server mode (at least in the same sense as is
* meant by this method). Basically, native code will
* set isServerMode to tell nsAppRunner; nsAppRunner will
* then call this method (implemented back in the same
* native code) at the appropriate time for any additional
* server-mode startup to be completed.
*
* This interface has these attributes:
* isServerMode - Boolean attribute indicating whether the application
@ -154,5 +160,5 @@ interface nsINativeAppSupport : nsISupports {
// Server mode.
attribute boolean isServerMode;
boolean cacheBrowserWindow(in nsIDOMWindow aWindow);
void startServerMode();
};

View File

@ -810,7 +810,16 @@ nsAppShellService::UnregisterTopLevelWindow(nsIXULWindow* aWindow)
if (!hiddenWin)
Quit();
#else
Quit();
// Check to see if we're in server mode, first.
if ( mNativeAppSupport ) {
PRBool serverMode = PR_FALSE;
mNativeAppSupport->GetIsServerMode( &serverMode );
if ( serverMode ) {
// Then don't quit.
return NS_OK;
}
}
Quit();
#endif
}
return rv;

View File

@ -256,8 +256,7 @@ static nsresult OpenWindow(const char *urlstr, const PRUnichar *args)
static nsresult
OpenChromeURL( const char * urlstr,
PRInt32 height = NS_SIZETOCONTENT,
PRInt32 width = NS_SIZETOCONTENT,
nsIDOMWindow **aResult = nsnull )
PRInt32 width = NS_SIZETOCONTENT )
{
#ifdef DEBUG_CMD_LINE
printf("OpenChromeURL(%s,%d,%d)\n",urlstr,height,width);
@ -278,20 +277,6 @@ OpenChromeURL( const char * urlstr,
nsIWebBrowserChrome::CHROME_ALL,
width, height,
getter_AddRefs(newWindow));
// Check if caller wants resulting window.
if(aResult) {
// Always return 0 if we don't have a window.
*aResult = nsnull;
// If window open was OK, then pass result as nsIDOMWindow.
if (NS_SUCCEEDED(rv) && newWindow) {
nsCOMPtr<nsIDocShell> docShell;
if (NS_SUCCEEDED(newWindow->GetDocShell(getter_AddRefs(docShell)))) {
nsCOMPtr<nsIDOMWindow> newDOMWin = do_GetInterface(docShell);
*aResult = newDOMWin;
NS_IF_ADDREF(*aResult);
}
}
}
return rv;
}
@ -636,7 +621,7 @@ static nsresult DoOnShutdown()
}
static nsresult OpenBrowserWindow(PRInt32 height, PRInt32 width, nsIDOMWindow **aResult)
static nsresult OpenBrowserWindow(PRInt32 height, PRInt32 width)
{
nsresult rv;
nsCOMPtr<nsICmdLineHandler> handler(do_GetService(NS_BROWSERSTARTUPHANDLER_CONTRACTID, &rv));
@ -646,7 +631,7 @@ static nsresult OpenBrowserWindow(PRInt32 height, PRInt32 width, nsIDOMWindow **
rv = handler->GetChromeUrlForTask(getter_Copies(chromeUrlForTask));
if (NS_FAILED(rv)) return rv;
rv = OpenChromeURL(chromeUrlForTask, height, width, aResult);
rv = OpenChromeURL(chromeUrlForTask, height, width);
if (NS_FAILED(rv)) return rv;
return rv;
@ -707,6 +692,22 @@ static nsresult Ensure1Window( nsICmdLineService* cmdLineArgs)
windowEnumerator->HasMoreElements(&more);
if ( !more )
{
// If starting up in server mode, then we do things differently.
nsCOMPtr<nsIAppShellService> appShellService(do_GetService(kAppShellServiceCID));
if (appShellService) {
nsCOMPtr<nsINativeAppSupport> nativeApp;
appShellService->GetNativeAppSupport(getter_AddRefs(nativeApp));
if (nativeApp) {
PRBool serverMode = PR_FALSE;
nativeApp->GetIsServerMode(&serverMode);
if (serverMode) {
// Create special Nav window.
nativeApp->StartServerMode();
return NS_OK;
}
}
}
// No window exists so lets create a browser one
PRInt32 height = NS_SIZETOCONTENT;
PRInt32 width = NS_SIZETOCONTENT;
@ -728,26 +729,7 @@ static nsresult Ensure1Window( nsICmdLineService* cmdLineArgs)
if ((const char*)tempString)
PR_sscanf(tempString, "%d", &height);
nsCOMPtr<nsIDOMWindow> browserWin;
rv = OpenBrowserWindow(height, width, getter_AddRefs(browserWin));
// See if we're in running in server mode.
if (NS_SUCCEEDED(rv) && browserWin) {
nsCOMPtr<nsIAppShellService> appShellService(do_GetService(kAppShellServiceCID));
if (appShellService) {
nsCOMPtr<nsINativeAppSupport> nativeApp;
appShellService->GetNativeAppSupport(getter_AddRefs(nativeApp));
if (nativeApp) {
PRBool serverMode = PR_FALSE;
nativeApp->GetIsServerMode(&serverMode);
if (serverMode) {
// Then cache (i.e., hide) this browser window.
PRBool cached = PR_FALSE;
nativeApp->CacheBrowserWindow(browserWin, &cached);
}
}
}
}
rv = OpenBrowserWindow(height, width);
}
}
return rv;

View File

@ -93,9 +93,7 @@ nsNativeAppSupportBase::GetIsServerMode(PRBool *aIsServerMode) {
}
NS_IMETHODIMP
nsNativeAppSupportBase::CacheBrowserWindow(nsIDOMWindow *aWindow, PRBool *aResult) {
NS_ENSURE_ARG( aResult );
*aResult = PR_FALSE;
nsNativeAppSupportBase::StartServerMode() {
return NS_OK;
}

View File

@ -253,8 +253,7 @@ public:
NS_IMETHOD Start( PRBool *aResult );
NS_IMETHOD Stop( PRBool *aResult );
NS_IMETHOD Quit();
NS_IMETHOD SetIsServerMode( PRBool aIsServerMode );
NS_IMETHOD CacheBrowserWindow( nsIDOMWindow *aWindow, PRBool *aResult );
NS_IMETHOD StartServerMode();
// The "old" Start method (renamed).
NS_IMETHOD StartDDE();
@ -280,10 +279,9 @@ private:
static PRBool InitTopicStrings();
static int FindTopic( HSZ topic );
static nsresult GetCmdLineArgs( LPBYTE request, nsICmdLineService **aResult );
static nsresult OpenWindow( const char *urlstr, const char *args, nsIDOMWindow **aResult = 0 );
static nsresult OpenWindow( const char *urlstr, const char *args );
static nsresult OpenBrowserWindow( const char *args );
static nsresult ReParent( nsIDOMWindowInternal *window, HWND newParent );
static nsCOMPtr<nsIDOMWindowInternal> mCachedWin;
static nsresult ReParent( nsISupports *window, HWND newParent );
static int mConversations;
enum {
topicOpenURL,
@ -604,7 +602,6 @@ const char * const topicNames[] = { "WWW_OpenURL",
"WWW_UnRegisterViewer" };
// Static member definitions.
nsCOMPtr<nsIDOMWindowInternal> nsNativeAppSupportWin::mCachedWin = 0;
int nsNativeAppSupportWin::mConversations = 0;
HSZ nsNativeAppSupportWin::mApplication = 0;
HSZ nsNativeAppSupportWin::mTopics[nsNativeAppSupportWin::topicCount] = { 0 };
@ -945,7 +942,7 @@ nsNativeAppSupportWin::HandleDDENotification( UINT uType, // transaction t
switch ( uType ) {
case XTYP_CONNECT:
// Make sure its for our service/topic.
if ( FindTopic( hsz1 ) < topicCount ) {
if ( FindTopic( hsz1 ) != -1 ) {
// We support this connection.
result = (HDDEDATA)1;
}
@ -1066,7 +1063,7 @@ nsCString nsNativeAppSupportWin::ParseDDEArg( HSZ args, int index ) {
static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
static HWND hwndForDOMWindow( nsIDOMWindowInternal * );
static HWND hwndForDOMWindow( nsISupports * );
void nsNativeAppSupportWin::ActivateLastWindow() {
nsCOMPtr<nsIWindowMediator> med( do_GetService( kWindowMediatorCID ) );
@ -1156,6 +1153,8 @@ nsNativeAppSupportWin::HandleRequest( LPBYTE request ) {
NS_SUCCEEDED( appShell->GetNativeAppSupport( getter_AddRefs( native ) ) ) &&
native ) {
native->SetIsServerMode( PR_FALSE );
// This closes app if there are no top-level windows.
appShell->UnregisterTopLevelWindow( 0 );
}
} else {
#if MOZ_DEBUG_DDE
@ -1339,14 +1338,10 @@ nsNativeAppSupportWin::GetCmdLineArgs( LPBYTE request, nsICmdLineService **aResu
}
nsresult
nsNativeAppSupportWin::OpenWindow( const char*urlstr, const char *args, nsIDOMWindow **aResult ) {
nsNativeAppSupportWin::OpenWindow( const char*urlstr, const char *args ) {
nsresult rv = NS_ERROR_FAILURE;
if ( aResult ) {
*aResult = 0;
}
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService("@mozilla.org/embedcomp/window-watcher;1"));
nsCOMPtr<nsISupportsString> sarg(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (sarg)
@ -1356,11 +1351,6 @@ nsNativeAppSupportWin::OpenWindow( const char*urlstr, const char *args, nsIDOMWi
nsCOMPtr<nsIDOMWindow> newWindow;
rv = wwatch->OpenWindow(0, urlstr, "_blank", "chrome,dialog=no,all",
sarg, getter_AddRefs(newWindow));
if ( aResult ) {
// Caller wants resulting window.
*aResult = newWindow;
NS_IF_ADDREF( *aResult );
}
#if MOZ_DEBUG_DDE
} else {
printf("Get WindowWatcher (or create string) failed\n");
@ -1388,7 +1378,7 @@ static LRESULT CALLBACK focusFilterProc( HWND hwnd, UINT uMsg, WPARAM wParam, LP
}
}
HWND hwndForDOMWindow( nsIDOMWindowInternal *window ) {
HWND hwndForDOMWindow( nsISupports *window ) {
nsCOMPtr<nsIScriptGlobalObject> ppScriptGlobalObj( do_QueryInterface(window) );
if ( !ppScriptGlobalObj ) {
return 0;
@ -1410,7 +1400,7 @@ HWND hwndForDOMWindow( nsIDOMWindowInternal *window ) {
}
nsresult
nsNativeAppSupportWin::ReParent( nsIDOMWindowInternal *window, HWND newParent ) {
nsNativeAppSupportWin::ReParent( nsISupports *window, HWND newParent ) {
HWND hMainFrame = hwndForDOMWindow( window );
if ( !hMainFrame ) {
return NS_ERROR_FAILURE;
@ -1513,14 +1503,6 @@ nsNativeAppSupportWin::OpenBrowserWindow( const char *args ) {
if ( !navWin ) {
// Have to open a new one.
break;
} else {
// Check if we're using the cached (hidden) window.
if ( mCachedWin == navWin ) {
// Drop window from cache.
mCachedWin = 0;
// Show it.
ReParent( navWin, 0 );
}
}
// Get content window.
navWin->GetContent( getter_AddRefs( content ) );
@ -1555,33 +1537,56 @@ nsNativeAppSupportWin::OpenBrowserWindow( const char *args ) {
return OpenWindow( "chrome://navigator/content", args );
}
// This opens a special browser window for purposes of priming the pump for
// server mode (getting stuff into the caching, loading .dlls, etc.). The
// window will have these attributes:
// - Load about:blank (no home page)
// - No toolbar (so there's no sidebar panels loaded, either)
// - Pass magic arg to cause window to close in onload handler.
NS_IMETHODIMP
nsNativeAppSupportWin::SetIsServerMode( PRBool aIsServerMode ) {
// Pas to base class implementation.
nsresult rv = nsNativeAppSupportBase::SetIsServerMode( aIsServerMode );
if ( NS_SUCCEEDED(rv) && !aIsServerMode && mCachedWin ) {
// Server mode is now off. Discard cached window.
mCachedWin->Close();
mCachedWin = 0;
nsNativeAppSupportWin::StartServerMode() {
// Create some of the objects we'll need.
nsCOMPtr<nsIWindowWatcher> ww(do_GetService("@mozilla.org/embedcomp/window-watcher;1"));
nsCOMPtr<nsISupportsWString> arg1(do_CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID));
nsCOMPtr<nsISupportsWString> arg2(do_CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID));
if ( !ww || !arg1 || !arg2 ) {
return NS_OK;
}
return rv;
}
NS_IMETHODIMP
nsNativeAppSupportWin::CacheBrowserWindow(nsIDOMWindow *aWindow, PRBool *aResult) {
NS_ENSURE_ARG( aResult );
*aResult = PR_FALSE;
// Cache this window if we don't already have one.
if ( !mCachedWin ) {
NS_ENSURE_ARG( aWindow );
nsresult rv = NS_OK;
mCachedWin = do_QueryInterface( aWindow, &rv );
if ( NS_SUCCEEDED( rv ) ) {
// We cached this window; tell caller so they don't close it.
*aResult = PR_TRUE;
// Re-parent it to hide it.
ReParent( mCachedWin, (HWND)MessageWindow() );
}
// Create the array for the arguments.
nsCOMPtr<nsISupportsArray> argArray;
NS_NewISupportsArray( getter_AddRefs( argArray ) );
if ( !argArray ) {
return NS_OK;
}
// arg1 is the url to load.
// arg2 is the string that tells navigator.js to auto-close.
arg1->SetData( NS_LITERAL_STRING( "about:blank" ).get() );
arg2->SetData( NS_LITERAL_STRING( "turbo=yes" ).get() );
// Put args into array.
if ( NS_FAILED( argArray->AppendElement( arg1 ) ) ||
NS_FAILED( argArray->AppendElement( arg2 ) ) ) {
return NS_OK;
}
// Now open the window.
nsCOMPtr<nsIDOMWindow> newWindow;
ww->OpenWindow( 0,
"chrome://navigator/content",
"_blank",
"chrome,dialog=no,toolbar=no",
argArray,
getter_AddRefs( newWindow ) );
if ( !newWindow ) {
return NS_OK;
}
// Hide this window by re-parenting it (to ensure it doesn't appear).
ReParent( newWindow, (HWND)MessageWindow() );
return NS_OK;
}

View File

@ -278,6 +278,7 @@ function Startup()
contentArea.addEventListener("load", loadEventHandlers, true);
contentArea.addEventListener("focus", contentAreaFrameFocus, true);
var turboMode = false;
// set default character set if provided
if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) {
if (window.arguments[1].indexOf("charset=") != -1) {
@ -286,6 +287,8 @@ function Startup()
//we should "inherit" the charset menu setting in a new window
appCore.setDefaultCharacterSet(arrayArgComponents[1]); //XXXjag see bug 67442
}
} else if (window.arguments[1].indexOf("turbo=yes") != -1) {
turboMode = true;
}
}
@ -314,7 +317,7 @@ function Startup()
if (!isPageCycling) {
var uriToLoad;
if (!appCore.cmdLineURLUsed) {
if (!appCore.cmdLineURLUsed && !turboMode) {
var cmdLineService = Components.classes["@mozilla.org/appshell/commandLineService;1"]
.getService(Components.interfaces.nsICmdLineService);
uriToLoad = cmdLineService.URLToLoad;
@ -337,6 +340,17 @@ function Startup()
loadURI(uriToLoad);
}
// Close the window now, if it's for turbo mode startup.
if ( turboMode ) {
// Set "command line used" flag. If we don't do this, then when a cmd line url
// for a "real* invocation comes in, we will override it with the "cmd line url"
// from the turbo-mode process (i.e., the home page).
appCore.cmdLineURLUsed = true;
// For some reason, window.close() directly doesn't work, so do it in the future.
window.setTimeout( "window.close()", 100 );
return;
}
// Focus the content area if the caller instructed us to.
if ("arguments" in window && window.arguments.length >= 3 && window.arguments[2] == true)
_content.focus();
@ -364,42 +378,6 @@ function BrowserFlushBookmarksAndHistory() {
}
}
function BrowserCanClose() {
// Check for "server mode."
try {
var appShellSvc = Components.classes["@mozilla.org/appshell/appShellService;1"]
.getService(Components.interfaces.nsIAppShellService);
var nativeSupport = appShellSvc.nativeAppSupport;
if (nativeSupport && nativeSupport.isServerMode) {
// Give native app a chance to cache this window.
if (nativeSupport.cacheBrowserWindow(window)) {
// Window is "cached" so don't close it.
// But flush bookmarks and history, as if we did close it.
BrowserFlushBookmarksAndHistory();
// Reset session history.
var webNav = getWebNavigation();
if (webNav) {
try {
webNav.sessionHistory.PurgeHistory( webNav.sessionHistory.count );
} catch(ex) {
}
}
// Go to blank page.
loadURI( "about:blank" );
// This stops the close.
return false;
}
}
} catch (ex) {
}
// Ok to close window.
return true;
}
function Shutdown()
{
var browser = getBrowser();

View File

@ -45,7 +45,7 @@ Contributor(s): ______________________________________. -->
<window id="main-window" xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="Startup()" onunload="Shutdown()" onclose="return BrowserCanClose()"
onload="Startup()" onunload="Shutdown()"
contenttitlesetting="true"
title="&mainWindow.title;"
titlemodifier="&mainWindow.titlemodifier;"

View File

@ -111,7 +111,7 @@
<command id="Browser:Open" oncommand="BrowserOpenWindow();"/>
<command id="Browser:Print" oncommand="BrowserPrint();"/>
<command id="cmd_quit"/>
<command id="cmd_close" oncommand="if(BrowserCanClose()){BrowserClose();}"/>
<command id="cmd_close" oncommand="BrowserClose()"/>
<!-- Edit Menu -->
<command id="cmd_undo"/>

View File

@ -121,11 +121,17 @@
* invoking the Hide() method on the nsISplashScreen
* interface maintained by the app shell service.
*
* cacheBrowserWindow - Takes an about-to-be-closed navigator window
* and "caches it" for later use. It returns an
* indicator of whether the window was actually
* cached. If that result is false, then the
* caller should close the window normally.
* startServerMode - Method that "starts" server mode. Typically, this
* will create a hidden Navigator window (and then close
* it) in order to fill the cache, load shared libraries,
* etc. Note that this method does not set the
* isServerMode attribute, nor does setting that attribute
* "start" server mode (at least in the same sense as is
* meant by this method). Basically, native code will
* set isServerMode to tell nsAppRunner; nsAppRunner will
* then call this method (implemented back in the same
* native code) at the appropriate time for any additional
* server-mode startup to be completed.
*
* This interface has these attributes:
* isServerMode - Boolean attribute indicating whether the application
@ -154,5 +160,5 @@ interface nsINativeAppSupport : nsISupports {
// Server mode.
attribute boolean isServerMode;
boolean cacheBrowserWindow(in nsIDOMWindow aWindow);
void startServerMode();
};

View File

@ -17,6 +17,24 @@ function goQuitApplication()
var windowManager = Components.classes['@mozilla.org/rdf/datasource;1?name=window-mediator'].getService();
var windowManagerInterface = windowManager.QueryInterface( Components.interfaces.nsIWindowMediator);
var enumerator = windowManagerInterface.getEnumerator( null );
var appShell = Components.classes['@mozilla.org/appshell/appShellService;1'].getService();
appShell = appShell.QueryInterface( Components.interfaces.nsIAppShellService );
// Get current server mode setting and turn it off while windows close.
var serverMode = false;
var nativeAppSupport = null;
try
{
nativeAppSupport = appShell.nativeAppSupport;
if ( nativeAppSupport )
{
serverMode = nativeAppSupport.isServerMode;
nativeAppSupport.isServerMode = false;
}
}
catch ( ex )
{
}
while ( enumerator.hasMoreElements() )
{
@ -31,13 +49,18 @@ function goQuitApplication()
{
// dump(" try to close \n" );
if ( !domWindow.tryToClose() )
{
// Restore server mode if it was set on entry.
if ( serverMode )
{
nativeAppSupport.isServerMode = true;
}
return false;
}
}
};
// call appshell exit
var appShell = Components.classes['@mozilla.org/appshell/appShellService;1'].getService();
appShell = appShell.QueryInterface( Components.interfaces.nsIAppShellService );
appShell.Quit();
return true;
}