package org.limewire.core.impl.mozilla; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import org.limewire.core.api.mozilla.LimeMozillaDownloadProgressListener; import org.limewire.logging.Log; import org.limewire.logging.LogFactory; import org.limewire.util.Objects; import org.mozilla.browser.MozillaExecutor; import org.mozilla.interfaces.nsIDOMDocument; import org.mozilla.interfaces.nsIDownload; import org.mozilla.interfaces.nsIDownloadManager; import org.mozilla.interfaces.nsIDownloadProgressListener; import org.mozilla.interfaces.nsIRequest; import org.mozilla.interfaces.nsISimpleEnumerator; import org.mozilla.interfaces.nsISupports; import org.mozilla.interfaces.nsIWebProgress; import org.mozilla.xpcom.Mozilla; import org.mozilla.xpcom.XPCOMException; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.name.Named; import com.limegroup.gnutella.DownloadManager; import com.limegroup.gnutella.downloader.CoreDownloader; /** * Provides a means of tracking what downloads have listeners already, and * adding listeners for those downloads which need them. */ @Singleton class LimeMozillaDownloadManagerListenerImpl implements org.limewire.core.api.mozilla.LimeMozillaDownloadManagerListener, nsIDownloadProgressListener { private static final Log LOG = LogFactory.getLog(LimeMozillaDownloadManagerListenerImpl.class); public static final String NS_IDOWNLOADMANAGER_CID = "@mozilla.org/download-manager;1"; private final Map<Long, LimeMozillaDownloadProgressListener> listeners; private final DownloadManager downloadManager; private final ScheduledExecutorService backgroundExecutor; private final XPComUtility xpComUtility; @Inject public LimeMozillaDownloadManagerListenerImpl( @Named("backgroundExecutor") ScheduledExecutorService backgroundExecutor, DownloadManager downloadManager, XPComUtility xpComUtility) { this.backgroundExecutor = Objects.nonNull(backgroundExecutor, "backgroundExecutor"); this.downloadManager = Objects.nonNull(downloadManager, "downloadManager"); this.xpComUtility = Objects.nonNull(xpComUtility, "xpComUtility"); this.listeners = new HashMap<Long, LimeMozillaDownloadProgressListener>(); } public synchronized void resumeDownloads() { nsIDownloadManager downloadManager = getDownloadManager(); nsISimpleEnumerator enumerator = downloadManager.getActiveDownloads(); while (enumerator.hasMoreElements()) { nsISupports elem = enumerator.getNext(); nsIDownload download = xpComUtility.proxy(elem, nsIDownload.class); long downloadId = download.getId(); try { downloadManager.resumeDownload(downloadId); } catch (XPCOMException e) { // can see the downloads in the ui and reusme them from there. // When first starting we don't know what downloads have already // started, so eat this exception here. } } } public synchronized void addMissingDownloads() { nsIDownloadManager downloadManager = getDownloadManager(); nsISimpleEnumerator enumerator = downloadManager.getActiveDownloads(); while (enumerator.hasMoreElements()) { nsISupports elem = enumerator.getNext(); nsIDownload download = xpComUtility.proxy(elem, nsIDownload.class); addListener(download, nsIDownloadManager.DOWNLOAD_QUEUED); } } private nsIDownloadManager getDownloadManager() { nsIDownloadManager downloadManager = xpComUtility.getServiceProxy(NS_IDOWNLOADMANAGER_CID, nsIDownloadManager.class); return downloadManager; } @Override public void onDownloadStateChange(short state, nsIDownload download) { addMissingDownloads(); } private synchronized boolean addListener(nsIDownload download, short state) { long downloadId = download.getId(); LimeMozillaDownloadProgressListener listener = listeners.get(downloadId); if (listener == null) { LimeMozillaDownloadProgressListenerImpl listenerImpl = new LimeMozillaDownloadProgressListenerImpl( this, backgroundExecutor, download, xpComUtility); listeners.put(download.getId(), listenerImpl); CoreDownloader downloader = (CoreDownloader)downloadManager.downloadFromMozilla(listenerImpl); listenerImpl.init(downloader, state); getDownloadManager().addListener(listenerImpl); return true; } return false; } @Override public void onProgressChange(nsIWebProgress webProgress, nsIRequest request, long curSelfProgress, long maxSelfProgress, long curTotalProgress, long maxTotalProgress, nsIDownload download) { // nothing to do for this listener } @Override public void onSecurityChange(nsIWebProgress webProgress, nsIRequest request, long state, nsIDownload download) { // don't care about this event. } @Override public void onStateChange(nsIWebProgress webProgress, nsIRequest request, long stateFlags, long status, nsIDownload download) { addMissingDownloads(); } @Override public void setDocument(nsIDOMDocument document) { // no mozilla window to use } @Override public nsIDOMDocument getDocument() { // no mozilla window to use return null; } @Override public nsISupports queryInterface(String uuid) { return Mozilla.queryInterface(this, uuid); } @Override public synchronized void removeListener( final LimeMozillaDownloadProgressListener limeMozillaDownloadProgressListener) { MozillaExecutor.mozSyncExec(new Runnable() { @Override public void run() { nsIDownloadManager downloadManager = getDownloadManager(); try { long downloadId = limeMozillaDownloadProgressListener.getDownloadId(); downloadManager.removeDownload(downloadId); } catch (XPCOMException e) { LOG.debug(e.getMessage(), e); } listeners.remove(limeMozillaDownloadProgressListener); } }); } }