/* -*- Mode: C++; tab-width: 4; 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.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ #include "nsProgressManager.h" #include "nsTopProgressManager.h" #include "nsSubProgressManager.h" static NS_DEFINE_IID(kITransferListenerIID, NS_ITRANSFERLISTENER_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); //////////////////////////////////////////////////////////////////////// // // nsProgressManager // // /** *
* This unholiness is used to keep reference counts straight for * all the wild and wooly ways that a progress manager can get * created. It recursively creates and installs progress managers, * walking the grid hierarchy up to the root, if necessary. Recursion * terminates as soon as a context is found with a progress manager * already installed. *
* ** Just for posterity, there are several ways that I can think of * that a progress manager might be born. We need to survive all * of them: *
* ** In each case, we need to make sure that we properly create * A top-level grid context and that everything gets refcounted * nicely. Could be nasty situations like, I'm loading a link * on a left frame, and the user gets bored and clicks a link * in the right frame! This should take care of that, too. *
*/ static void pm_RecursiveEnsure(MWContext* context) { if (! context) return; if (context->progressManager) return; if (context->grid_parent) { pm_RecursiveEnsure(context->grid_parent); context->progressManager = new nsSubProgressManager(context); } else { context->progressManager = new nsTopProgressManager(context); } } void nsProgressManager::Ensure(MWContext* context) { pm_RecursiveEnsure(context); if (context->progressManager) context->progressManager->AddRef(); } void nsProgressManager::Release(MWContext* context) { if (! context) return; // Note that we DO NOT set the context's progressManager // slot to NULL. This is due to the obscene reference // counting that we do: the slot will be set to NULL by // the progressManager's destructor. if (context->progressManager) context->progressManager->Release(); } nsProgressManager::nsProgressManager(MWContext* context) : fContext(context) { NS_INIT_REFCNT(); } nsProgressManager::~nsProgressManager(void) { // HERE is where we null the context's progressManager slot. We // wait until the progress manager is actually destroyed, because // there are several ways that a reference to the progress manager // might be held, and unfortunately, the only public way to access // the progress manager is through the contexts. if (fContext) { fContext->progressManager = NULL; fContext = NULL; } } //////////////////////////////////////////////////////////////////////// NS_IMPL_ADDREF(nsProgressManager); NS_IMPL_RELEASE(nsProgressManager); nsresult nsProgressManager::QueryInterface(const nsIID& iid, void** result) { if (iid.Equals(kITransferListenerIID)) { (*result) = (void*) ((nsITransferListener*) this); AddRef(); return NS_OK; } else if (iid.Equals(kISupportsIID)) { (*result) = (void*) ((nsISupports*) this); AddRef(); return NS_OK; } return NS_NOINTERFACE; }