Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Private Member Functions | Private Attributes
nsXPInstallManager Class Reference

#include <nsXPInstallManager.h>

Collaboration diagram for nsXPInstallManager:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsXPInstallManager ()
virtual ~nsXPInstallManager ()
NS_DECL_ISUPPORTS
NS_DECL_NSIXPILISTENER
NS_DECL_NSIXPIDIALOGSERVICE
NS_DECL_NSIXPINSTALLMANAGER
NS_DECL_NSIOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSPICERTNOTIFICATION
NS_IMETHOD 
InitManager (nsIScriptGlobalObject *aGlobalObject, nsXPITriggerInfo *aTrigger, PRUint32 aChromeType)

Private Member Functions

nsresult InitManagerInternal ()
NS_IMETHOD DownloadNext ()
void Shutdown ()
NS_IMETHOD GetDestinationFile (nsString &url, nsILocalFile **file)
NS_IMETHOD LoadParams (PRUint32 aCount, const PRUnichar **aPackageList, nsIDialogParamBlock **aParams)
PRBool TimeToUpdate (PRTime now)
PRBool VerifyHash (nsXPITriggerItem *aItem)
PRInt32 GetIndexFromURL (const PRUnichar *aUrl)

Private Attributes

nsXPITriggerInfomTriggers
nsXPITriggerItemmItem
PRTime mLastUpdate
PRUint32 mNextItem
PRInt32 mNumJars
PRUint32 mChromeType
PRInt32 mContentLength
PRInt32 mOutstandingCertLoads
PRBool mDialogOpen
PRBool mCancelled
PRBool mSelectChrome
PRBool mNeedsShutdown
nsCOMPtr< nsIXPIProgressDialogmDlg
nsCOMPtr< nsISoftwareUpdatemInstallSvc
nsCOMPtr< nsIDOMWindowInternalmParentWindow

Detailed Description

Definition at line 78 of file nsXPInstallManager.h.


Constructor & Destructor Documentation

Definition at line 113 of file nsXPInstallManager.cpp.

  : mTriggers(0), mItem(0), mNextItem(0), mNumJars(0), mChromeType(NOT_CHROME),
    mContentLength(0), mDialogOpen(PR_FALSE), mCancelled(PR_FALSE),
    mSelectChrome(PR_FALSE), mNeedsShutdown(PR_FALSE)
{
    // 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();
}

Here is the call graph for this function:

Definition at line 127 of file nsXPInstallManager.cpp.

{
    NS_ASSERTION(!mTriggers, "Shutdown not called, triggers still alive");
}

Member Function Documentation

Definition at line 603 of file nsXPInstallManager.cpp.

{
    nsresult rv;
    mContentLength = 0;

    if (mCancelled)
    {
        // Don't download any more if we were cancelled
        Shutdown();
        return NS_OK;
    }

    if ( mNextItem < mTriggers->Size() )
    {
        //-------------------------------------------------
        // There are items to download, get the next one
        //-------------------------------------------------
        mItem = (nsXPITriggerItem*)mTriggers->Get(mNextItem++);

        NS_ASSERTION( mItem, "bogus Trigger slipped through" );
        NS_ASSERTION( !mItem->mURL.IsEmpty(), "bogus trigger");
        if ( !mItem || mItem->mURL.IsEmpty() )
        {
            // serious problem with trigger! Can't notify anyone of the
            // error without the URL, just try to carry on.
            return DownloadNext();
        }

        // --- Tell the dialog we're starting a download
        if (mDlg)
            mDlg->OnStateChange( mNextItem-1, nsIXPIProgressDialog::DOWNLOAD_START, 0 );

        if ( mItem->IsFileURL() && mChromeType == NOT_CHROME )
        {
            //--------------------------------------------------
            // Already local, we can open it where it is
            //--------------------------------------------------
            nsCOMPtr<nsIURI> pURL;
            rv = NS_NewURI(getter_AddRefs(pURL), mItem->mURL);

            if (NS_SUCCEEDED(rv))
            {
                nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(pURL,&rv);
                if (fileURL)
                {
                    nsCOMPtr<nsIFile> localFile;
                    rv = fileURL->GetFile(getter_AddRefs(localFile));
                    if (NS_SUCCEEDED(rv))
                    {
                        mItem->mFile = do_QueryInterface(localFile,&rv);
                    }
                }
            }

            if ( NS_FAILED(rv) || !mItem->mFile )
            {
                // send error status back
                if (mDlg)
                    mDlg->OnStateChange( mNextItem-1,
                                         nsIXPIProgressDialog::INSTALL_DONE,
                                         nsInstall::UNEXPECTED_ERROR );
                mTriggers->SendStatus( mItem->mURL.get(),
                                       nsInstall::UNEXPECTED_ERROR );
                mItem->mFile = 0;
            }
            else if (mDlg)
            {
                mDlg->OnStateChange( mNextItem-1,
                                     nsIXPIProgressDialog::DOWNLOAD_DONE, 0);
            }

            // --- on to the next one
            return DownloadNext();
        }
        else
        {
            //--------------------------------------------------
            // We have one to download
            //--------------------------------------------------
            rv = GetDestinationFile(mItem->mURL, getter_AddRefs(mItem->mFile));
            if (NS_SUCCEEDED(rv))
            {
                nsCOMPtr<nsIURI> pURL;
                rv = NS_NewURI(getter_AddRefs(pURL), mItem->mURL);
                if (NS_SUCCEEDED(rv))
                {
                    nsCOMPtr<nsIChannel> channel;

                    rv = NS_NewChannel(getter_AddRefs(channel), pURL, nsnull, nsnull, this);
                    if (NS_SUCCEEDED(rv))
                    {
                        rv = channel->AsyncOpen(this, nsnull);
                    }
                }
            }

            if (NS_FAILED(rv))
            {
                // announce failure
                if (mDlg)
                    mDlg->OnStateChange( mNextItem-1,
                                         nsIXPIProgressDialog::INSTALL_DONE,
                                         nsInstall::DOWNLOAD_ERROR );
                mTriggers->SendStatus( mItem->mURL.get(),
                                       nsInstall::DOWNLOAD_ERROR );
                mItem->mFile = 0;

                // We won't get Necko callbacks so start the next one now
                return DownloadNext();
            }
        }
    }
    else
    {
        //------------------------------------------------------
        // all downloaded, queue them for installation
        //------------------------------------------------------

        // can't cancel from here on cause we can't undo installs in a multitrigger
        for (PRUint32 i = 0; i < mTriggers->Size(); ++i)
        {
            mItem = (nsXPITriggerItem*)mTriggers->Get(i);
            if ( !mItem || !mItem->mFile )
            {
                // notification for these errors already handled
                continue;
            }

            // If there was hash info in the trigger, but
            // there wasn't a hash object created, then the
            // algorithm used isn't known.

            if (mItem->mHashFound && !mItem->mHasher)
            {
                // report failure
                mTriggers->SendStatus( mItem->mURL.get(), nsInstall::INVALID_HASH_TYPE );
                if (mDlg)
                    mDlg->OnStateChange( i, nsIXPIProgressDialog::INSTALL_DONE,
                                         nsInstall::INVALID_HASH_TYPE );
                continue;
            }

            // Don't install if we can't verify the hash (if specified)
            if (mItem->mHasher && !VerifyHash(mItem))
            {
                // report failure
                mTriggers->SendStatus( mItem->mURL.get(), nsInstall::INVALID_HASH );
                if (mDlg)
                    mDlg->OnStateChange( i, nsIXPIProgressDialog::INSTALL_DONE,
                                         nsInstall::INVALID_HASH );
                continue;
            }

            // We've got one to install; increment count first so we
            // don't have to worry about thread timing.
            PR_AtomicIncrement(&mNumJars);

            if ( mChromeType == NOT_CHROME ) {
                rv = mInstallSvc->InstallJar( mItem->mFile,
                                              mItem->mURL.get(),
                                              mItem->mArguments.get(),
                                              mItem->mPrincipal,
                                              mItem->mFlags,
                                              this );
            }
            else {
                rv = mInstallSvc->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 );
                if (mDlg)
                    mDlg->OnStateChange( i, nsIXPIProgressDialog::INSTALL_DONE,
                                         nsInstall::UNEXPECTED_ERROR );
            }
        }

        if ( mNumJars == 0 )
        {
            // We must clean ourself up now -- we won't be called back
            Shutdown();
        }
    }

    return rv;
}

Here is the call graph for this function:

Definition at line 930 of file nsXPInstallManager.cpp.

{
    NS_ENSURE_ARG_POINTER(file);

    nsresult rv;
    nsAutoString leaf;

    PRInt32 pos = url.RFindChar('/');
    url.Mid( leaf, pos+1, url.Length() );

    nsCOMPtr<nsIProperties> directoryService =
             do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);

    if (mChromeType == NOT_CHROME )
    {
        // a regular XPInstall, not chrome
        if (NS_SUCCEEDED(rv))
        {
            nsCOMPtr<nsILocalFile> temp;
            rv = directoryService->Get(NS_OS_TEMP_DIR,
                                       NS_GET_IID(nsIFile),
                                       getter_AddRefs(temp));
            if (NS_SUCCEEDED(rv))
            { 
                temp->AppendNative(NS_LITERAL_CSTRING("tmp.xpi"));
                temp->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
                *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->Append(leaf);
                    userChrome->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644);
                    *file = userChrome;
                    NS_IF_ADDREF(*file);
                }
            }
        }
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1197 of file nsXPInstallManager.cpp.

{
    // --- figure out which index corresponds to this URL
    PRUint32 i;
    for (i=0; i < mTriggers->Size(); i++)
    {
        if ( (nsXPITriggerInfo*)mTriggers->Get(i)->mURL.Equals(aUrl) )
            break;
    }
    NS_ASSERTION( i < mTriggers->Size(), "invalid result URL!" );

    return i;
}

Here is the call graph for this function:

Definition at line 210 of file nsXPInstallManager.cpp.

{
    if ( !aTriggers || aTriggers->Size() == 0 )
    {
        NS_WARNING("XPInstallManager called with no trigger info!");
        NS_RELEASE_THIS();
        return NS_ERROR_INVALID_POINTER;
    }

    nsresult rv = NS_OK;

    mNeedsShutdown = PR_TRUE;
    mTriggers = aTriggers;
    mChromeType = aChromeType;

    mParentWindow = do_QueryInterface(aGlobalObject);

    // Start downloading initial chunks looking for signatures,
    mOutstandingCertLoads = mTriggers->Size();

    nsXPITriggerItem *item = mTriggers->Get(--mOutstandingCertLoads);

    nsCOMPtr<nsIURI> uri;
    NS_NewURI(getter_AddRefs(uri), NS_ConvertUCS2toUTF8(item->mURL));
    nsCOMPtr<nsIStreamListener> listener = new CertReader(uri, nsnull, this);
    if (listener)
        rv = NS_OpenURI(listener, nsnull, uri);
    else
        rv = NS_ERROR_OUT_OF_MEMORY;

    if (NS_FAILED(rv)) {
        Shutdown();
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 248 of file nsXPInstallManager.cpp.

{
    nsresult rv;
    PRBool OKtoInstall = PR_FALSE; // initialize to secure state

    //-----------------------------------------------------
    // *** Do not return early after this point ***
    //
    // We have to clean up the triggers in case of error
    //-----------------------------------------------------

    // --- use embedding dialogs if any registered
    nsCOMPtr<nsIXPIDialogService> dlgSvc(do_CreateInstance(NS_XPIDIALOGSERVICE_CONTRACTID));
    if ( !dlgSvc )
        dlgSvc = this; // provide our own dialogs

    // --- make sure we can get the install service
    mInstallSvc = do_GetService(nsSoftwareUpdate::GetCID(), &rv);

    // --- prepare dialog params
    PRUint32 numTriggers = mTriggers->Size();
    PRUint32 numStrings = 4 * numTriggers;
    const PRUnichar** packageList =
        (const PRUnichar**)malloc( sizeof(PRUnichar*) * numStrings );

    if ( packageList && NS_SUCCEEDED(rv) )
    {
        // populate the list. The list doesn't own the strings
        for ( PRUint32 i=0, j=0; i < numTriggers; i++ )
        {
            nsXPITriggerItem *item = mTriggers->Get(i);
            packageList[j++] = item->mName.get();
            packageList[j++] = item->GetSafeURLString();
            packageList[j++] = item->mIconURL.get();
            packageList[j++] = item->mCertName.get();
        }

        //-----------------------------------------------------
        // Get permission to install
        //-----------------------------------------------------

#ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI
        if ( mChromeType == CHROME_SKIN )
        {
            // We may want to enable the simple installation UI once
            // bug 343037 is fixed

            // skins get a simpler/friendlier dialog
            // XXX currently not embeddable
            OKtoInstall = ConfirmChromeInstall( mParentWindow, packageList );
        }
        else
        {
#endif
            rv = dlgSvc->ConfirmInstall( mParentWindow,
                                         packageList,
                                         numStrings,
                                         &OKtoInstall );
            if (NS_FAILED(rv))
                OKtoInstall = PR_FALSE;
#ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI
        }
#endif

        if (OKtoInstall)
        {
            nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
            if (os)
                os->AddObserver(this, XPI_PROGRESS_TOPIC, PR_TRUE);

            //-----------------------------------------------------
            // Open the progress dialog
            //-----------------------------------------------------

            rv = dlgSvc->OpenProgressDialog( packageList, numStrings, this );
        }
    }
    else
        rv = NS_ERROR_OUT_OF_MEMORY;

    //-----------------------------------------------------
    // cleanup and signal callbacks if there were errors
    //-----------------------------------------------------

    if (packageList)
        free(packageList);

    PRInt32 cbstatus = 0;  // callback status
    if (NS_FAILED(rv))
        cbstatus = nsInstall::UNEXPECTED_ERROR;
    else if (!OKtoInstall)
        cbstatus = nsInstall::USER_CANCELLED;

    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;
}

Here is the call graph for this function:

NS_IMETHODIMP nsXPInstallManager::LoadParams ( PRUint32  aCount,
const PRUnichar **  aPackageList,
nsIDialogParamBlock **  aParams 
) [private]

Definition at line 908 of file nsXPInstallManager.cpp.

{
    nsresult rv;
    nsCOMPtr<nsIDialogParamBlock> paramBlock = do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &rv);
    if (NS_SUCCEEDED(rv))
    {
        // set OK and Cancel buttons
        paramBlock->SetInt( 0, 2 );
        // pass in number of strings
        paramBlock->SetInt( 1, aCount );
        // add strings
        paramBlock->SetNumberStrings( aCount );
        for (PRUint32 i = 0; i < aCount; i++)
            paramBlock->SetString( i, aPackageList[i] );
    }

    NS_IF_ADDREF(*aParams = paramBlock);
    return rv;
}

Here is the call graph for this function:

Definition at line 840 of file nsXPInstallManager.cpp.

{
    if (mDlg)
    {
        // tell the dialog it can go away
        mDlg->OnStateChange(0, nsIXPIProgressDialog::DIALOG_CLOSE, 0 );
        mDlg = nsnull;
        mDialogOpen = PR_FALSE;
    }

    if (mNeedsShutdown)
    {
        mNeedsShutdown = PR_FALSE;

        // Send remaining status notifications if we were cancelled early
        nsXPITriggerItem* item;
        while ( mNextItem < mTriggers->Size() )
        {
            item = (nsXPITriggerItem*)mTriggers->Get(mNextItem++);
            if ( item && !item->mURL.IsEmpty() )
            {
                mTriggers->SendStatus( item->mURL.get(),
                                       nsInstall::USER_CANCELLED );
            }
        }

        // Clean up downloaded files (regular install only, not chrome installs)
        nsCOMPtr<nsIFile> tmpSpec;
        if ( mChromeType == NOT_CHROME )
        {
            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);
            }
        }

        nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
        if (os)
        {
            nsresult rv;
            nsCOMPtr<nsIProxyObjectManager> pmgr =
                        do_GetService(kProxyObjectManagerCID, &rv);
            if (pmgr)
            {
                nsCOMPtr<nsIObserverService> pos;
                rv = pmgr->GetProxyForObject( NS_UI_THREAD_EVENTQ,
                                              NS_GET_IID(nsIObserverService),
                                              os,
                                              PROXY_SYNC | PROXY_ALWAYS,
                                              getter_AddRefs(pos) );
                if (NS_SUCCEEDED(rv))
                    pos->RemoveObserver(this, XPI_PROGRESS_TOPIC);
            }
        }

        if (mTriggers)
        {
            delete mTriggers;
            mTriggers = nsnull;
        }

        NS_RELEASE_THIS();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsXPInstallManager::TimeToUpdate ( PRTime  now) [inline, private]

Definition at line 105 of file nsXPInstallManager.cpp.

{
       // XXX lets revisit this when dveditz gets back

       return PR_TRUE;
}

Definition at line 808 of file nsXPInstallManager.cpp.

{
    NS_ASSERTION(aItem, "Null nsXPITriggerItem passed to VerifyHash");

    nsresult rv;
    if (!aItem->mHasher)
      return PR_FALSE;
    
    nsCOMPtr<nsIInputStream> stream;
    rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), aItem->mFile);
    if (NS_FAILED(rv)) return PR_FALSE;

    rv = aItem->mHasher->UpdateFromStream(stream, PR_UINT32_MAX);
    if (NS_FAILED(rv)) return PR_FALSE;

    nsCAutoString binaryHash;
    rv = aItem->mHasher->Finish(PR_FALSE, binaryHash);
    if (NS_FAILED(rv)) return PR_FALSE;

    char* hash = nsnull;
    for (PRUint32 i=0; i < binaryHash.Length(); ++i)
    {
        hash = PR_sprintf_append(hash,"%.2x", (PRUint8)binaryHash[i]);
    }

    PRBool result = aItem->mHash.EqualsIgnoreCase(hash);

    PR_smprintf_free(hash);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 127 of file nsXPInstallManager.h.

Definition at line 123 of file nsXPInstallManager.h.

Definition at line 124 of file nsXPInstallManager.h.

Definition at line 126 of file nsXPInstallManager.h.

Definition at line 131 of file nsXPInstallManager.h.

Definition at line 132 of file nsXPInstallManager.h.

Definition at line 119 of file nsXPInstallManager.h.

Definition at line 120 of file nsXPInstallManager.h.

Definition at line 129 of file nsXPInstallManager.h.

Definition at line 121 of file nsXPInstallManager.h.

Definition at line 122 of file nsXPInstallManager.h.

Definition at line 125 of file nsXPInstallManager.h.

Definition at line 134 of file nsXPInstallManager.h.

Definition at line 128 of file nsXPInstallManager.h.

Definition at line 118 of file nsXPInstallManager.h.


The documentation for this class was generated from the following files: