remove expensive setAttribute method! forward all status calls

to our little brother in JS. This should make setting status and starting / stopping the meteors
so much faster! Remove knowledge of the webshell,
and webshell window which we no longer need to keep track of.
r=alecf
This commit is contained in:
mscott%netscape.com 2000-04-14 02:48:57 +00:00
parent aed8db1c33
commit d489a2379d
2 changed files with 50 additions and 191 deletions

View File

@ -22,6 +22,7 @@
#include "msgCore.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "nsMsgStatusFeedback.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDocumentViewer.h"
@ -31,11 +32,10 @@
#include "nsIObserverService.h"
#include "nsIDocShell.h"
#define MSGFEEDBACK_TIMER_INTERVAL 500
nsMsgStatusFeedback::nsMsgStatusFeedback() :
mWebShell(nsnull),
mWebShellWindow(nsnull),
m_meteorsSpinning(PR_FALSE),
m_lastPercent(0),
mQueuedMeteorStarts(0),
@ -47,19 +47,14 @@ nsMsgStatusFeedback::nsMsgStatusFeedback() :
nsMsgStatusFeedback::~nsMsgStatusFeedback()
{
EndObserving();
}
//
// nsISupports
//
NS_IMPL_THREADSAFE_ISUPPORTS3(nsMsgStatusFeedback,
NS_IMPL_THREADSAFE_ISUPPORTS2(nsMsgStatusFeedback,
nsIMsgStatusFeedback,
nsIDocumentLoaderObserver,
nsIObserver)
// nsIDocumentLoaderObserver
nsIDocumentLoaderObserver)
// nsIDocumentLoaderObserver methods
@ -80,22 +75,24 @@ nsMsgStatusFeedback::OnStartDocumentLoad(nsIDocumentLoader* aLoader, nsIURI* aUR
{
nsIDOMWindow *aWindow = mWindow;
nsCOMPtr<nsIScriptGlobalObject>
globalScript(do_QueryInterface(aWindow));
nsCOMPtr<nsIDocShell> docShell;
if (globalScript)
globalScript(do_QueryInterface(aWindow));
nsCOMPtr<nsIDocShell> docShell;
if (globalScript)
globalScript->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsIWebShell> webshell(do_QueryInterface(docShell));
nsCOMPtr<nsIWebShell> rootWebshell;
nsCOMPtr<nsIWebShell> webshell(do_QueryInterface(docShell));
nsCOMPtr<nsIWebShell> rootWebshell;
if (webshell)
webshell->GetRootWebShell(*getter_AddRefs(rootWebshell));
if (rootWebshell)
if (rootWebshell)
{
// Kick start the throbber
StartMeteors();
setAttribute( rootWebshell, "Messenger:Status", "value", "Loading Document..." );
StartMeteors();
ShowStatusString(nsAutoString("Loading Document...").GetUnicode());
// Enable the Stop buton
setAttribute( rootWebshell, "canStop", "disabled", "" );
// setAttribute( rootWebshell, "canStop", "disabled", "" );
}
}
return rv;
@ -119,81 +116,27 @@ nsMsgStatusFeedback::OnEndDocumentLoad(nsIDocumentLoader* aLoader, nsIChannel* c
{
nsIDOMWindow *aWindow = mWindow;
nsCOMPtr<nsIScriptGlobalObject>
globalScript(do_QueryInterface(aWindow));
nsCOMPtr<nsIDocShell> docShell;
globalScript(do_QueryInterface(aWindow));
nsCOMPtr<nsIDocShell> docShell;
if (globalScript)
globalScript->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsIWebShell> webshell(do_QueryInterface(docShell));
nsCOMPtr<nsIWebShell> rootWebshell;
nsCOMPtr<nsIWebShell> webshell(do_QueryInterface(docShell));
nsCOMPtr<nsIWebShell> rootWebshell;
if (webshell)
webshell->GetRootWebShell(*getter_AddRefs(rootWebshell));
if (rootWebshell)
{
// stop the throbber
StopMeteors();
setAttribute( rootWebshell, "Messenger:Status", "value", "Document: Done" );
StopMeteors();
ShowStatusString(nsAutoString("Document: Done").GetUnicode());
// Disable the Stop buton
setAttribute( rootWebshell, "canStop", "disabled", "true" );
//setAttribute( rootWebshell, "canStop", "disabled", "true" );
}
}
return rv;
}
static const char *prefix = "component://netscape/appshell/component/browser/window";
void nsMsgStatusFeedback::BeginObserving()
{
// Get observer service.
nsresult rv = NS_OK;
NS_WITH_SERVICE(nsIObserverService, svc, NS_OBSERVERSERVICE_PROGID, &rv);
if ( NS_SUCCEEDED( rv ) && svc )
{
// Add/Remove object as observer of web shell window topics.
nsAutoString topic1(prefix);
topic1 += ";status";
rv = svc->AddObserver( this, topic1.GetUnicode() );
}
return;
}
void nsMsgStatusFeedback::EndObserving()
{
// Get observer service.
nsresult rv = NS_OK;
NS_WITH_SERVICE(nsIObserverService, svc, NS_OBSERVERSERVICE_PROGID, &rv);
if ( NS_SUCCEEDED( rv ) && svc )
{
// Add/Remove object as observer of web shell window topics.
nsAutoString topic1(prefix);
topic1 += ";status";
rv = svc->RemoveObserver( this, topic1.GetUnicode() );
}
return;
}
NS_IMETHODIMP nsMsgStatusFeedback::Observe( nsISupports *aSubject,
const PRUnichar *aTopic,
const PRUnichar *someData )
{
nsresult rv = NS_OK;
// We only are interested if aSubject is our web shell window.
if ( aSubject && mWebShellWindow )
{
nsCOMPtr<nsIWebShellWindow> window = do_QueryInterface(aSubject, &rv);
if ( NS_SUCCEEDED(rv) && window && (window.get() == mWebShellWindow) )
{
nsAutoString topic1 = prefix;
topic1 += ";status";
if ( topic1 == aTopic )
rv = ShowStatusString(someData);
} // if window matches our window
} // if we have a window to worry about
return rv;
}
NS_IMETHODIMP nsMsgStatusFeedback::OnStartURLLoad(nsIDocumentLoader* loader, nsIChannel* channel)
{
return NS_OK;
@ -218,7 +161,8 @@ NS_IMETHODIMP
nsMsgStatusFeedback::ShowStatusString(const PRUnichar *status)
{
nsAutoString statusMsg = status;
setAttribute( mWebShell, "Messenger:Status", "value", statusMsg );
if (mStatusFeedback)
mStatusFeedback->ShowStatusString(status);
return NS_OK;
}
@ -247,12 +191,9 @@ nsMsgStatusFeedback::ShowProgress(PRInt32 percentage)
}
m_lastProgressTime = nowMS;
if (percentage >= 0)
setAttribute(mWebShell, "Messenger:LoadingProgress", "mode","normal");
strPercentage.Append(percentage, 10);
setAttribute( mWebShell, "Messenger:LoadingProgress", "value", strPercentage);
if (mStatusFeedback)
mStatusFeedback->ShowProgress(percentage);
return NS_OK;
}
@ -334,110 +275,31 @@ nsMsgStatusFeedback::StopMeteors()
NS_IMETHODIMP nsMsgStatusFeedback::CloseWindow()
{
EndObserving();
mWindow = nsnull;
mWebShell = nsnull;
mWebShellWindow = nsnull;
mStatusFeedback = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsMsgStatusFeedback::SetWebShell(nsIWebShell *shell, nsIDOMWindow *aWindow)
{
if (aWindow)
{
nsCOMPtr<nsIScriptGlobalObject>
globalScript(do_QueryInterface(aWindow));
nsCOMPtr<nsIDocShell> docShell;
if (globalScript)
globalScript->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsIWebShell> webshell(do_QueryInterface(docShell));
nsCOMPtr<nsIWebShell> rootWebshell;
if (webshell)
{
webshell->GetRootWebShell(mWebShell);
nsIWebShell *root = mWebShell;
NS_RELEASE(root); // don't hold reference
// get the webshell window too....
nsCOMPtr<nsIWebShellContainer> topLevelWindow;
webshell->GetTopLevelWindow(getter_AddRefs(topLevelWindow));
if (topLevelWindow)
{
nsCOMPtr<nsIWebShellWindow> webWindow = do_QueryInterface(topLevelWindow);
// do NOT!!! keep an owning reference on the webshell window..it owns us...
mWebShellWindow = webWindow;
}
}
}
if (aWindow)
{
nsCOMPtr<nsISupports> xpConnectObj;
nsCOMPtr<nsPIDOMWindow> piDOMWindow(do_QueryInterface(aWindow));
if (piDOMWindow)
{
nsAutoString msgStatusFeedbackWinId("MsgStatusFeedback");
piDOMWindow->GetObjectProperty(msgStatusFeedbackWinId.GetUnicode(), getter_AddRefs(xpConnectObj));
mStatusFeedback = do_QueryInterface(xpConnectObj);
}
}
mWindow = aWindow;
BeginObserving();
return NS_OK;
}
static int debugSetAttr = 0;
nsresult nsMsgStatusFeedback::setAttribute( nsIWebShell *shell,
const char *id,
const char *name,
const nsString &value )
{
if (!mWebShell)
return NS_OK;
nsresult rv = NS_OK;
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(shell));
nsCOMPtr<nsIContentViewer> cv;
rv = docShell ? docShell->GetContentViewer(getter_AddRefs(cv))
: NS_ERROR_NULL_POINTER;
if ( cv ) {
// Up-cast.
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
if ( docv ) {
// Get the document from the doc viewer.
nsCOMPtr<nsIDocument> doc;
rv = docv->GetDocument(*getter_AddRefs(doc));
if ( doc ) {
// Up-cast.
nsCOMPtr<nsIDOMXULDocument> xulDoc( do_QueryInterface(doc) );
if ( xulDoc )
{
// Find specified element.
nsCOMPtr<nsIDOMElement> elem;
rv = xulDoc->GetElementById( id, getter_AddRefs(elem) );
if ( elem ) {
// Set the text attribute.
rv = elem->SetAttribute( name, value );
if ( debugSetAttr ) {
char *p = value.ToNewCString();
printf("setting busy to %s\n", p);
delete [] p;
}
if ( rv != NS_OK ) {
if (debugSetAttr) printf("SetAttribute failed, rv=0x%X\n",(int)rv);
}
} else {
if (debugSetAttr) printf("GetElementByID failed, rv=0x%X\n",(int)rv);
}
} else {
if (debugSetAttr) printf("Upcast to nsIDOMHTMLDocument failed\n");
}
} else {
if (debugSetAttr) printf("GetDocument failed, rv=0x%X\n",(int)rv);
}
} else {
if (debugSetAttr) printf("Upcast to nsIDocumentViewer failed\n");
}
} else {
if (debugSetAttr) printf("GetContentViewer failed, rv=0x%X\n",(int)rv);
}
return rv;
}
//
// timer callbacks that resolve closure
//
@ -472,7 +334,8 @@ nsMsgStatusFeedback::NotifyStartMeteors(nsITimer *aTimer)
if (mQueuedMeteorStops > 0) return;
// actually start the meteors
setAttribute(mWebShell, "Messenger:Throbber", "busy", "true");
if (mStatusFeedback)
mStatusFeedback->StartMeteors();
m_meteorsSpinning = PR_TRUE;
}
@ -488,7 +351,7 @@ nsMsgStatusFeedback::NotifyStopMeteors(nsITimer* aTimer)
if (mQueuedMeteorStarts > 0) return;
// actually stop the meteors
setAttribute( mWebShell, "Messenger:Throbber", "busy", "false" );
if (mStatusFeedback)
mStatusFeedback->StopMeteors();
m_meteorsSpinning = PR_FALSE;
}

View File

@ -33,7 +33,6 @@
#include "nsIMsgStatusFeedback.h"
class nsMsgStatusFeedback : public nsIMsgStatusFeedback,
public nsIObserver,
public nsIDocumentLoaderObserver
{
public:
@ -42,19 +41,12 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGSTATUSFEEDBACK
NS_DECL_NSIOBSERVER
// nsIDocumntLoaderObserver
NS_DECL_NSIDOCUMENTLOADEROBSERVER
nsresult setAttribute( nsIWebShell *shell,
const char *id,
const char *name,
const nsString &value );
protected:
nsIWebShell *mWebShell;
nsIDOMWindow *mWindow;
nsIWebShellWindow *mWebShellWindow;
PRBool m_meteorsSpinning;
PRInt32 m_lastPercent;
PRInt64 m_lastProgressTime;
@ -74,6 +66,10 @@ protected:
// timer callbacks w/resolved closure
void NotifyStartMeteors(nsITimer *aTimer);
void NotifyStopMeteors(nsITimer *aTimer);
// the JS status feedback implementation object...eventually this object
// will replace this very C++ class you are looking at.
nsCOMPtr<nsIMsgStatusFeedback> mStatusFeedback;
};
#endif // _nsMsgStatusFeedback_h