Mozilla/mozilla/xpinstall/src/nsXPInstallManager.cpp
jaggernaut%netscape.com 436d43f211 Bug 104158: Use NS_LITERAL_STRING instead of XXXWithConversion("..."). r=bryner, rs=alecf
git-svn-id: svn://10.0.0.236/trunk@110579 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-16 11:58:03 +00:00

968 lines
29 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Daniel Veditz <dveditz@netscape.com>
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nscore.h"
#include "nsFileSpec.h"
#include "pratom.h"
#include "nsISupports.h"
#include "nsIServiceManager.h"
#include "nsIURL.h"
#include "nsIFileChannel.h"
#include "nsITransport.h"
#include "nsIFileTransportService.h"
#include "nsIOutputStream.h"
#include "nsNetUtil.h"
#include "nsIInputStream.h"
#include "nsIFileStreams.h"
#include "nsIStreamListener.h"
#include "nsISoftwareUpdate.h"
#include "nsSoftwareUpdateIIDs.h"
#include "nsTextFormatter.h"
#include "nsXPITriggerInfo.h"
#include "nsXPInstallManager.h"
#include "nsInstallTrigger.h"
#include "nsInstallProgressDialog.h"
#include "nsInstallResources.h"
#include "nsSpecialSystemDirectory.h"
#include "nsIProxyObjectManager.h"
#include "nsIDOMWindowInternal.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsReadableUtils.h"
#include "nsProxiedService.h"
#include "nsIPromptService.h"
#include "nsIScriptGlobalObject.h"
#include "nsISupportsPrimitives.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
#include "nsIEventQueueService.h"
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
#define PROGRESS_BAR 'n'
#define BARBER_POLE 'u'
#define UPDATE_DLG(x) (((x) - mLastUpdate) > 250000)
// Mac can't handle PRTime as integers, must go through this hell
inline PRBool nsXPInstallManager::TimeToUpdate(PRTime now)
{
// XXX lets revisit this when dveditz gets back
return PR_TRUE;
}
nsXPInstallManager::nsXPInstallManager()
: mTriggers(0), mItem(0), mNextItem(0), mNumJars(0),
mFinalizing(PR_FALSE), mCancelled(PR_FALSE), mChromeType(0),
mSelectChrome(PR_TRUE), mContentLength(0)
{
NS_INIT_ISUPPORTS();
// we need to own ourself because we have a longer
// lifetime than the scriptlet that created us.
NS_ADDREF_THIS();
// initialize mLastUpdate to the current time
mLastUpdate = PR_Now();
// get the resourced xpinstall string bundle
mStringBundle = nsnull;
nsIStringBundleService *service;
nsresult rv = nsServiceManager::GetService( kStringBundleServiceCID,
NS_GET_IID(nsIStringBundleService),
(nsISupports**) &service );
if (NS_SUCCEEDED(rv) && service)
{
rv = service->CreateBundle( XPINSTALL_BUNDLE_URL,
getter_AddRefs(mStringBundle) );
nsServiceManager::ReleaseService( kStringBundleServiceCID, service );
}
}
nsXPInstallManager::~nsXPInstallManager()
{
if (mTriggers)
delete mTriggers;
}
NS_IMPL_THREADSAFE_ADDREF( nsXPInstallManager );
NS_IMPL_THREADSAFE_RELEASE( nsXPInstallManager );
NS_IMETHODIMP
nsXPInstallManager::QueryInterface(REFNSIID aIID,void** aInstancePtr)
{
if (!aInstancePtr)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(NS_GET_IID(nsIXPIListener)))
*aInstancePtr = NS_STATIC_CAST(nsIXPIListener*,this);
else if (aIID.Equals(NS_GET_IID(nsIStreamListener)))
*aInstancePtr = NS_STATIC_CAST(nsIStreamListener*,this);
else if (aIID.Equals(NS_GET_IID(nsPIXPIManagerCallbacks)))
*aInstancePtr = NS_STATIC_CAST(nsPIXPIManagerCallbacks*,this);
else if (aIID.Equals(NS_GET_IID(nsIProgressEventSink)))
*aInstancePtr = NS_STATIC_CAST(nsIProgressEventSink*,this);
else if (aIID.Equals(NS_GET_IID(nsIInterfaceRequestor)))
*aInstancePtr = NS_STATIC_CAST(nsIInterfaceRequestor*,this);
else if (aIID.Equals(NS_GET_IID(nsISupports)))
*aInstancePtr = NS_STATIC_CAST( nsISupports*, NS_STATIC_CAST(nsIXPIListener*,this));
else
*aInstancePtr = 0;
nsresult status;
if ( !*aInstancePtr )
status = NS_NOINTERFACE;
else
{
NS_ADDREF_THIS();
status = NS_OK;
}
return status;
}
NS_IMETHODIMP
nsXPInstallManager::InitManager(nsIScriptGlobalObject* aGlobalObject, nsXPITriggerInfo* aTriggers, PRUint32 aChromeType)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIDialogParamBlock> ioParamBlock;
PRBool OKtoInstall = PR_FALSE;
mTriggers = aTriggers;
mChromeType = aChromeType;
mNeedsShutdown = PR_TRUE;
if ( !mTriggers || mTriggers->Size() == 0 )
{
rv = NS_ERROR_INVALID_POINTER;
NS_RELEASE_THIS();
return rv;
}
//-----------------------------------------------------
// Create the nsIDialogParamBlock to pass the trigger
// list to the dialog
//-----------------------------------------------------
rv = nsComponentManager::CreateInstance("@mozilla.org/embedcomp/dialogparam;1",
nsnull,
NS_GET_IID(nsIDialogParamBlock),
getter_AddRefs(ioParamBlock));
if ( NS_SUCCEEDED( rv ) )
{
LoadDialogWithNames(ioParamBlock);
if (mChromeType == 0 || mChromeType > CHROME_SAFEMAX )
OKtoInstall = ConfirmInstall(aGlobalObject, ioParamBlock);
else
OKtoInstall = ConfirmChromeInstall(aGlobalObject);
}
// --- create and open the progress dialog
if (NS_SUCCEEDED(rv) && OKtoInstall)
{
nsInstallProgressDialog* dlg;
nsCOMPtr<nsISupports> Idlg;
dlg = new nsInstallProgressDialog(this);
if ( dlg )
{
rv = dlg->QueryInterface( NS_GET_IID(nsIXPIProgressDlg),
getter_AddRefs(Idlg) );
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIProxyObjectManager> pmgr =
do_GetService(kProxyObjectManagerCID, &rv);
if (NS_SUCCEEDED(rv))
{
rv = pmgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIXPIProgressDlg),
Idlg, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs(mDlg) );
}
if (NS_SUCCEEDED(rv))
{
rv = mDlg->Open(ioParamBlock);
}
}
}
else
rv = NS_ERROR_OUT_OF_MEMORY;
}
PRInt32 cbstatus = 0; // callback status
if (NS_SUCCEEDED(rv) && !OKtoInstall )
cbstatus = nsInstall::USER_CANCELLED;
else if (NS_FAILED(rv))
cbstatus = nsInstall::UNEXPECTED_ERROR;
if ( cbstatus != 0 )
{
// --- inform callbacks of error
for (PRUint32 i = 0; i < mTriggers->Size(); i++)
{
mTriggers->SendStatus( mTriggers->Get(i)->mURL.get(),
cbstatus );
}
// -- must delete ourselves if not continuing
NS_RELEASE_THIS();
}
return rv;
}
PRBool nsXPInstallManager::ConfirmInstall(nsIScriptGlobalObject* aGlobalObject, nsIDialogParamBlock* ioParamBlock)
{
nsresult rv = NS_OK;
PRBool result = PR_FALSE;
nsCOMPtr<nsIDOMWindowInternal> parentWindow =
do_QueryInterface(aGlobalObject);
if (parentWindow)
{
nsCOMPtr<nsIDOMWindow> newWindow;
nsCOMPtr<nsISupportsArray> array;
nsCOMPtr<nsISupportsInterfacePointer> ifptr =
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
ifptr->SetData(ioParamBlock);
ifptr->SetDataIID(&NS_GET_IID(nsIDialogParamBlock));
rv = parentWindow->OpenDialog(NS_LITERAL_STRING("chrome://communicator/content/xpinstall/institems.xul"),
NS_LITERAL_STRING("_blank"),
NS_LITERAL_STRING("chrome,modal,titlebar,resizable"),
ifptr, getter_AddRefs( newWindow));
if (NS_SUCCEEDED(rv))
{
//Now get which button was pressed from the ParamBlock
PRInt32 buttonPressed = 0;
ioParamBlock->GetInt( 0, &buttonPressed );
result = buttonPressed ? PR_FALSE : PR_TRUE;
}
}
return result;
}
PRBool nsXPInstallManager::ConfirmChromeInstall(nsIScriptGlobalObject* aGlobalObject)
{
nsXPITriggerItem* item = (nsXPITriggerItem*)mTriggers->Get(0);
// get the dialog strings
nsresult rv;
nsXPIDLString applyNowText;
nsXPIDLString confirmFormat;
PRUnichar* confirmText = nsnull;
nsCOMPtr<nsIStringBundle> xpiBundle;
nsCOMPtr<nsIStringBundleService> bundleSvc =
do_GetService( kStringBundleServiceCID, &rv );
if (NS_SUCCEEDED(rv) && bundleSvc)
{
rv = bundleSvc->CreateBundle( XPINSTALL_BUNDLE_URL,
getter_AddRefs(xpiBundle) );
if (NS_SUCCEEDED(rv) && xpiBundle)
{
if ( mChromeType == CHROME_LOCALE )
{
xpiBundle->GetStringFromName(
NS_LITERAL_STRING("ApplyNowLocale").get(),
getter_Copies(applyNowText));
xpiBundle->GetStringFromName(
NS_LITERAL_STRING("ConfirmLocale").get(),
getter_Copies(confirmFormat));
}
else
{
xpiBundle->GetStringFromName(
NS_LITERAL_STRING("ApplyNowSkin").get(),
getter_Copies(applyNowText));
xpiBundle->GetStringFromName(
NS_LITERAL_STRING("ConfirmSkin").get(),
getter_Copies(confirmFormat));
}
confirmText = nsTextFormatter::smprintf(confirmFormat,
item->mName.get(),
item->mURL.get());
}
}
// confirmation dialog
PRBool bInstall = PR_FALSE;
if (confirmText)
{
nsCOMPtr<nsIDOMWindowInternal> parentWindow(do_QueryInterface(aGlobalObject));
if (parentWindow)
{
nsCOMPtr<nsIPromptService> dlgService(do_GetService("@mozilla.org/embedcomp/prompt-service;1"));
if (dlgService)
{
rv = dlgService->ConfirmCheck( parentWindow,
nsnull,
confirmText,
applyNowText,
&mSelectChrome,
&bInstall );
}
}
}
return bInstall;
}
NS_IMETHODIMP nsXPInstallManager::DialogOpened(nsISupports* aWindow)
{
nsresult rv;
mParentWindow = do_QueryInterface(aWindow, &rv);
DownloadNext();
return rv;
}
NS_IMETHODIMP nsXPInstallManager::DownloadNext()
{
nsresult rv;
mContentLength = 0;
if (mCancelled)
{
Shutdown();
return NS_OK; // don't try to download anymore
}
if ( mNextItem < mTriggers->Size() )
{
// download the next item in list
mItem = (nsXPITriggerItem*)mTriggers->Get(mNextItem++);
NS_ASSERTION( mItem, "bogus Trigger slipped through" );
NS_ASSERTION( mItem->mURL.Length() > 0, "bogus trigger");
if ( !mItem || mItem->mURL.Length() == 0 )
{
// XXX serious problem with trigger! try to carry on
rv = DownloadNext();
}
else if ( mItem->IsFileURL() && mChromeType == 0 )
{
nsCOMPtr<nsIURI> pURL;
rv = NS_NewURI(getter_AddRefs(pURL), mItem->mURL);
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(pURL);
if (!fileURL)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIFile> localFile;
rv = fileURL->GetFile(getter_AddRefs(localFile));
if (NS_FAILED(rv))
{
// serious problem with trigger! try to carry on
mTriggers->SendStatus( mItem->mURL.get(),
nsInstall::DOWNLOAD_ERROR );
mItem->mFile = 0;
}
else
{
mItem->mFile = do_QueryInterface(localFile);
rv = DownloadNext();
}
}
}
else
{
// We have one to download -- figure out the destination file name
rv = GetDestinationFile(mItem->mURL, getter_AddRefs(mItem->mFile));
if (NS_SUCCEEDED(rv))
{
// --- start the download
nsCOMPtr<nsIURI> pURL;
rv = NS_NewURI(getter_AddRefs(pURL), mItem->mURL);
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIChannel> channel;
rv = NS_OpenURI(getter_AddRefs(channel), pURL, nsnull, nsnull, this);
if (NS_SUCCEEDED(rv))
{
rv = channel->AsyncOpen(this, nsnull);
}
}
}
if (NS_FAILED(rv))
{
// announce failure
mTriggers->SendStatus( mItem->mURL.get(),
nsInstall::DOWNLOAD_ERROR );
mItem->mFile = 0;
// carry on with the next one
rv = DownloadNext();
}
}
}
else
{
// all downloaded, queue them for installation
// can't cancel from here on cause we can't undo installs in a multitrigger
if (mDlg)
mDlg->StartInstallPhase();
nsCOMPtr<nsISoftwareUpdate> softupdate =
do_GetService(nsSoftwareUpdate::GetCID(), &rv);
if (NS_SUCCEEDED(rv))
{
for (PRUint32 i = 0; i < mTriggers->Size(); ++i)
{
mItem = (nsXPITriggerItem*)mTriggers->Get(i);
if ( mItem && mItem->mFile )
{
// We've got one to install; increment count first so we
// don't have to worry about thread timing.
PR_AtomicIncrement(&mNumJars);
if ( mChromeType == 0 ) {
rv = softupdate->InstallJar(mItem->mFile,
mItem->mURL.get(),
mItem->mArguments.get(),
mParentWindow,
mItem->mFlags,
this );
}
else {
rv = softupdate->InstallChrome(mChromeType,
mItem->mFile,
mItem->mURL.get(),
mItem->mName.get(),
mSelectChrome,
this );
}
if (NS_FAILED(rv))
{
// it failed so remove it from the count
PR_AtomicDecrement(&mNumJars);
// send the error status to any trigger callback
mTriggers->SendStatus( mItem->mURL.get(),
nsInstall::UNEXPECTED_ERROR );
}
}
}
}
else
{
; // XXX gotta clean up all those files...
}
if ( mNumJars == 0 )
{
// We must clean ourself up now -- we won't be called back
Shutdown();
}
}
return rv;
}
NS_IMETHODIMP
nsXPInstallManager::CancelInstall()
{
mCancelled = PR_TRUE; // set by dialog thread
return NS_OK;
}
void nsXPInstallManager::Shutdown()
{
if (mDlg)
{
mDlg->Close();
mDlg = nsnull;
}
if (mNeedsShutdown)
{
mNeedsShutdown = PR_FALSE;
// Clean up downloaded files, regular XPInstall only not chrome installs
nsXPITriggerItem* item;
nsCOMPtr<nsIFile> tmpSpec;
if ( mChromeType == 0 )
{
for (PRUint32 i = 0; i < mTriggers->Size(); i++ )
{
item = NS_STATIC_CAST(nsXPITriggerItem*, mTriggers->Get(i));
if ( item && item->mFile && !item->IsFileURL() )
item->mFile->Remove(PR_FALSE);
}
}
NS_RELEASE_THIS();
}
}
/*-----------------------------------------------------
** LoadDialogWithNames loads the param block for the
** javascript/xul dialog with the list of modules to
** be installed and their source locations
**----------------------------------------------------*/
void nsXPInstallManager::LoadDialogWithNames(nsIDialogParamBlock* ioParamBlock)
{
nsXPITriggerItem *triggerItem;
nsString moduleName, URL;
PRInt32 offset = 0, numberOfDialogTreeElements = 0;
PRUint32 i=0, paramIndex=0;
//Must multiply the number of triggers by 2 because
//the dialog contains the name and url as 2 separate elements
numberOfDialogTreeElements = (mTriggers->Size() * 2);
ioParamBlock->SetNumberStrings(numberOfDialogTreeElements);
ioParamBlock->SetInt(0,2); //set the Ok and Cancel buttons
ioParamBlock->SetInt(1,numberOfDialogTreeElements);
for (i=0; i < mTriggers->Size(); i++)
{
triggerItem = mTriggers->Get(i);
//Check to see if this trigger item has a pretty name
if(!(moduleName = triggerItem->mName).IsEmpty())
{
ioParamBlock->SetString(paramIndex, moduleName.get());
paramIndex++;
URL = triggerItem->mURL;
offset = URL.RFind("/");
if (offset != -1)
{
URL.Cut(offset + 1, URL.Length() - 1);
ioParamBlock->SetString(paramIndex, URL.get());
}
paramIndex++;
}
else
{
//triggerItem does not have a pretty name so parse the url for the file name
//then use that as the pretty name
moduleName = triggerItem->mURL;
URL = triggerItem->mURL;
offset = moduleName.RFind("/");
if (offset != -1)
{
moduleName.Cut(0, offset + 1);
ioParamBlock->SetString(paramIndex, moduleName.get());
paramIndex++;
URL.Cut(offset + 1, URL.Length() - 1);
ioParamBlock->SetString(paramIndex, URL.get());
}
paramIndex++;
}
}
}
NS_IMETHODIMP
nsXPInstallManager::GetDestinationFile(nsString& url, nsILocalFile* *file)
{
NS_ENSURE_ARG_POINTER(file);
nsresult rv;
nsString leaf;
PRInt32 pos = url.RFindChar('/');
url.Mid( leaf, pos+1, url.Length() );
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
if (mChromeType == 0 )
{
// a regular XPInstall, not chrome
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsILocalFile> temp;
directoryService->Get(NS_OS_TEMP_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(temp));
temp->AppendUnicode(leaf.get());
MakeUnique(temp);
*file = temp;
NS_IF_ADDREF(*file);
}
}
else
{
// a chrome install, download straight to final destination
if (NS_SUCCEEDED(rv)) // Getting directoryService
{
nsCOMPtr<nsILocalFile> userChrome;
// Get the user's Chrome directory, create if necessary
rv = directoryService->Get(NS_APP_USER_CHROME_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(userChrome));
NS_ASSERTION(NS_SUCCEEDED(rv) && userChrome,
"App_UserChromeDirectory not defined!");
if (NS_SUCCEEDED(rv))
{
PRBool exists;
rv = userChrome->Exists(&exists);
if (NS_SUCCEEDED(rv) && !exists)
{
rv = userChrome->Create(nsIFile::DIRECTORY_TYPE, 0775);
}
if (NS_SUCCEEDED(rv))
{
userChrome->AppendUnicode(leaf.get());
MakeUnique(userChrome);
*file = userChrome;
NS_IF_ADDREF(*file);
}
}
}
}
return rv;
}
NS_IMETHODIMP
nsXPInstallManager::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
{
nsresult rv = NS_ERROR_FAILURE;
NS_ASSERTION( mItem && mItem->mFile, "XPIMgr::OnStartRequest bad state");
if ( mItem && mItem->mFile )
{
NS_ASSERTION( !mItem->mOutStream, "Received double OnStartRequest from Necko");
NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
nsCOMPtr<nsIFileTransportService> fts =
do_GetService( kFileTransportServiceCID, &rv );
if (NS_SUCCEEDED(rv) && !mItem->mOutStream)
{
nsCOMPtr<nsITransport> outChannel;
rv = fts->CreateTransport(mItem->mFile,
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
0664,
getter_AddRefs( outChannel));
if (NS_SUCCEEDED(rv))
{
// Open output stream.
rv = outChannel->OpenOutputStream(0, -1, 0, getter_AddRefs( mItem->mOutStream ) );
}
}
}
return rv;
}
NS_IMETHODIMP
nsXPInstallManager::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
nsresult status)
{
nsresult rv;
switch( status )
{
case NS_BINDING_SUCCEEDED:
rv = NS_OK;
break;
case NS_BINDING_FAILED:
case NS_BINDING_ABORTED:
rv = status;
// XXX need to note failure, both to send back status
// to the callback, and also so we don't try to install
// this probably corrupt file.
break;
default:
rv = NS_ERROR_ILLEGAL_VALUE;
}
NS_ASSERTION( mItem, "Bad state in XPIManager");
NS_ASSERTION( mItem->mOutStream, "XPIManager: output stream doesn't exist");
if ( mItem && mItem->mOutStream )
{
mItem->mOutStream->Close();
mItem->mOutStream = nsnull;
}
if (NS_FAILED(rv))
{
if ( mItem->mFile )
{
PRBool flagExists;
nsFileSpec fspec;
nsresult rv2 ;
rv2 = mItem->mFile->Exists(&flagExists);
if (NS_SUCCEEDED(rv2) && flagExists)
mItem->mFile->Remove(PR_FALSE);
mItem->mFile = 0;
}
mTriggers->SendStatus( mItem->mURL.get(),
nsInstall::DOWNLOAD_ERROR );
}
DownloadNext();
return rv;
}
NS_IMETHODIMP
nsXPInstallManager::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
nsIInputStream *pIStream,
PRUint32 sourceOffset,
PRUint32 length)
{
PRUint32 amt;
nsresult err;
char buffer[8*1024];
PRUint32 writeCount;
//printf("nsXPInstallManager::OnDataAvailable\n");
if (mCancelled)
{
// returning an error will stop the download. We may get extra
// OnData calls if they were already queued so beware
if (mDlg)
{
mDlg->Close();
mDlg = nsnull;
}
return NS_ERROR_FAILURE;
}
do
{
err = pIStream->Read(buffer, sizeof(buffer), &amt);
if (amt == 0) break;
if (NS_FAILED(err))
{
//printf("pIStream->Read Failed! %d", err);
return err;
}
err = mItem->mOutStream->Write( buffer, amt, &writeCount);
if (NS_FAILED(err) || writeCount != amt)
{
return NS_ERROR_FAILURE;
}
length -= amt;
} while (length > 0);
return NS_OK;
}
NS_IMETHODIMP
nsXPInstallManager::OnProgress(nsIRequest* request, nsISupports *ctxt, PRUint32 aProgress, PRUint32 aProgressMax)
{
nsresult rv = NS_OK;
PRTime now = PR_Now();
if (mDlg && !mCancelled && TimeToUpdate(now))
{
if (mContentLength < 1) {
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request,&rv);
NS_ASSERTION(channel, "should have a channel");
if (NS_FAILED(rv)) return rv;
rv = channel->GetContentLength(&mContentLength);
if (NS_FAILED(rv)) return rv;
}
mLastUpdate = now;
rv = mDlg->SetProgress(aProgress, mContentLength, PROGRESS_BAR);
}
return rv;
}
NS_IMETHODIMP
nsXPInstallManager::OnStatus(nsIRequest* request, nsISupports *ctxt,
nsresult aStatus, const PRUnichar *aStatusArg)
{
nsresult rv;
PRTime now = PR_Now();
if (mDlg && !mCancelled && TimeToUpdate(now))
{
mLastUpdate = now;
nsCOMPtr<nsIStringBundleService> sbs = do_GetService(kStringBundleServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsXPIDLString msg;
rv = sbs->FormatStatusMessage(aStatus, aStatusArg, getter_Copies(msg));
if (NS_FAILED(rv)) return rv;
return mDlg->SetActionText(msg);
}
else
return NS_OK;
}
// nsIInterfaceRequestor method
NS_IMETHODIMP
nsXPInstallManager::GetInterface(const nsIID & eventSinkIID, void* *_retval)
{
return QueryInterface(eventSinkIID, (void**)_retval);
}
// IXPIListener methods
NS_IMETHODIMP
nsXPInstallManager::BeforeJavascriptEvaluation(const PRUnichar *URL)
{
nsresult rv = NS_OK;
mFinalizing = PR_FALSE;
if (mDlg)
{
mDlg->SetProgress( 0, 0, BARBER_POLE ); // turn on the barber pole
PRUnichar tmp[] = { '\0' };
mDlg->SetActionText(tmp);
}
return rv;
}
NS_IMETHODIMP
nsXPInstallManager::AfterJavascriptEvaluation(const PRUnichar *URL)
{
PR_AtomicDecrement( &mNumJars );
if ( mNumJars == 0 )
Shutdown();
return NS_OK;
}
NS_IMETHODIMP
nsXPInstallManager::InstallStarted(const PRUnichar *URL, const PRUnichar *UIPackageName)
{
if (!mDlg)
return NS_OK;
mDlg->SetActionText(nsnull);
return mDlg->SetHeading( nsString(UIPackageName).get() );
}
NS_IMETHODIMP
nsXPInstallManager::ItemScheduled(const PRUnichar *message)
{
PRTime now = PR_Now();
if (mDlg && TimeToUpdate(now))
{
mLastUpdate = now;
return mDlg->SetActionText( nsString(message).get() );
}
else
return NS_OK;
}
NS_IMETHODIMP
nsXPInstallManager::FinalizeProgress(const PRUnichar *message, PRInt32 itemNum, PRInt32 totNum)
{
if (!mDlg)
return NS_OK;
nsresult rv = NS_OK;
if (!mFinalizing)
{
mFinalizing = PR_TRUE;
if (mStringBundle)
{
nsString rsrcName(NS_LITERAL_STRING("FinishingInstallMsg"));
const PRUnichar* ucRsrcName = rsrcName.get();
PRUnichar* ucRsrcVal = nsnull;
rv = mStringBundle->GetStringFromName(ucRsrcName, &ucRsrcVal);
if (NS_SUCCEEDED(rv) && ucRsrcVal)
{
rv = mDlg->SetActionText( ucRsrcVal );
nsCRT::free(ucRsrcVal);
}
}
}
PRTime now = PR_Now();
if (TimeToUpdate(now))
{
mLastUpdate = now;
rv = mDlg->SetProgress( itemNum, totNum, PROGRESS_BAR );
}
return rv;
}
NS_IMETHODIMP
nsXPInstallManager::FinalStatus(const PRUnichar *URL, PRInt32 status)
{
mTriggers->SendStatus( URL, status );
return NS_OK;
}
NS_IMETHODIMP
nsXPInstallManager::LogComment(const PRUnichar* comment)
{
return NS_OK;
}