|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
|
/* |
|
|
* 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): |
|
|
* Pierre Phaneuf <pp@ludusdesign.com> |
|
|
*/ |
|
|
|
|
|
#include "stdafx.h" |
|
|
//#include "nsEscape.h" |
|
|
#include <wininet.h> |
|
|
#include <cderr.h> |
|
|
#include "UnknownContentTypeHandler.h" |
|
|
#include "Utils.h" |
|
|
#include "MozUtils.h" |
|
|
#include "MfcEmbed.h" |
|
|
#include "prtime.h" |
|
|
|
|
|
#include "nsIFileURL.h" |
|
|
#include "nsIHttpChannel.h" |
|
|
#include "nsIMIMEInfo.h" |
|
|
#include "nsIWindowWatcher.h" |
|
|
#include "nsCExternalHandlerService.h" |
|
|
|
|
|
const PRTime _pr_filetime_offset = 116444736000000000i64; |
|
|
const PRTime _pr_filetime_divisor = 10i64; |
|
|
|
|
|
void |
|
|
_PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm) |
|
|
{ |
|
|
PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime)); |
|
|
CopyMemory(prtm, filetime, sizeof(PRTime)); |
|
|
*prtm = (*prtm - _pr_filetime_offset) / 10i64; |
|
|
} |
|
|
|
|
|
PRTime PRNow(void) |
|
|
{ |
|
|
PRTime prt; |
|
|
FILETIME ft; |
|
|
SYSTEMTIME st; |
|
|
|
|
|
GetSystemTime(&st); |
|
|
SystemTimeToFileTime(&st, &ft); |
|
|
_PR_FileTimeToPRTime(&ft, &prt); |
|
|
return prt; |
|
|
} |
|
|
|
|
|
#include "nsIPropertyBag2.h" |
|
|
#include "KmInstaller.h" |
|
|
|
|
|
/* void handleContent (in string aContentType, in nsIInterfaceRequestor aWindowContext, in nsIRequest aRequest); */ |
|
|
NS_IMETHODIMP CUnknownContentTypeHandler::HandleContent(const char * aContentType, nsIInterfaceRequestor *aWindowContext, nsIRequest *aRequest) |
|
|
{ |
|
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); |
|
|
if (!channel) return NS_ERROR_WONT_HANDLE_CONTENT; |
|
|
|
|
|
nsCOMPtr<nsIURI> uri; |
|
|
channel->GetURI(getter_AddRefs(uri)); |
|
|
nsCOMPtr<nsIURL> url = do_QueryInterface(uri); |
|
|
if (!url) return NS_ERROR_WONT_HANDLE_CONTENT; |
|
|
|
|
|
nsCOMPtr<nsIURI> referer; |
|
|
nsCOMPtr<nsIPropertyBag2> prop = do_QueryInterface(aRequest); |
|
|
if (prop) { |
|
|
prop->GetPropertyAsInterface(NS_LITERAL_STRING("docshell.internalReferrer"), |
|
|
NS_GET_IID(nsIURI), getter_AddRefs(referer)); |
|
|
} |
|
|
|
|
|
nsString filename; |
|
|
channel->GetContentDispositionFilename(filename); |
|
|
|
|
|
if (!filename.Length()) { |
|
|
nsCString fuck; |
|
|
url->GetFileName(fuck); |
|
|
filename = NS_ConvertUTF8toUTF16(fuck); |
|
|
} |
|
|
|
|
|
if (!KmInstaller::InstallFromUrl(KmInstaller::TYPE_SKIN, uri, filename)) |
|
|
return NS_ERROR_WONT_HANDLE_CONTENT; |
|
|
|
|
|
aRequest->Cancel(NS_BINDING_ABORTED); |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP |
|
|
CUnknownContentTypeHandler::Show(CWnd* parent) |
|
|
{ |
|
|
nsresult rv; |
|
|
nsCOMPtr<nsIHelperAppLauncherDialog> kungFuDeathGrip(this); |
|
|
|
|
|
if (theApp.preferences.GetBool("kmeleon.download.SaveUnkownContent", true)) |
|
|
{ |
|
|
if (theApp.preferences.bAskOpenSave) |
|
|
{ |
|
|
CoInitialize(NULL); |
|
|
|
|
|
COpenSaveDlg dlg(parent); |
|
|
|
|
|
USES_CONVERSION; |
|
|
// Set the filename |
|
|
nsString filename; |
|
|
mAppLauncher->GetSuggestedFileName(filename); |
|
|
dlg.m_csFilename = W2CT(filename.get()); |
|
|
|
|
|
// Set the mime type |
|
|
|
|
|
nsCOMPtr<nsIMIMEInfo> mimeInfo; |
|
|
mAppLauncher->GetMIMEInfo(getter_AddRefs(mimeInfo)); |
|
|
dlg.m_csFiletype = GetTypeName(); |
|
|
|
|
|
// Set the source |
|
|
nsCOMPtr<nsIURI> uri; |
|
|
rv = mAppLauncher->GetSource(getter_AddRefs(uri)); |
|
|
if(NS_SUCCEEDED(rv)) |
|
|
{ |
|
|
nsCString sourceURI; |
|
|
uri->GetHost(sourceURI); |
|
|
|
|
|
if (!sourceURI.IsEmpty()) |
|
|
dlg.m_csSource = NSUTF8StringToCString(sourceURI); |
|
|
else |
|
|
{ |
|
|
uri->GetScheme(sourceURI); |
|
|
if (sourceURI.Equals(nsCString("file"))) |
|
|
dlg.m_csSource = _T("localhost"); |
|
|
} |
|
|
} |
|
|
|
|
|
switch (dlg.DoModal()) { |
|
|
|
|
|
case IDOK: |
|
|
rv = mAppLauncher->SaveToDisk(nullptr, false); |
|
|
break; |
|
|
case IDOPEN: |
|
|
if (mimeInfo) { |
|
|
// This code prevent gecko to throw an error when |
|
|
// trying to open a file with no association |
|
|
bool hasHandler; |
|
|
mimeInfo->GetHasDefaultHandler(&hasHandler); |
|
|
if (!hasHandler) |
|
|
mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); |
|
|
} |
|
|
rv = mAppLauncher->LaunchWithApplication(nullptr, PR_FALSE); |
|
|
break; |
|
|
default: |
|
|
rv = mAppLauncher->Cancel(NS_ERROR_ABORT); |
|
|
} |
|
|
|
|
|
CoUninitialize(); |
|
|
} |
|
|
else |
|
|
rv = mAppLauncher->SaveToDisk(nullptr, false); |
|
|
} |
|
|
else |
|
|
rv = mAppLauncher->Cancel(NS_ERROR_ABORT); |
|
|
|
|
|
// If the window that launched the download is "about:blank" |
|
|
// then we need to close it. |
|
|
BOOL closeParent = !GetUriForDOMWindow(mDomWindow).Compare(_T("about:blank")); |
|
|
if (mDomWindow && closeParent) |
|
|
{ |
|
|
nsCOMPtr<nsIWindowWatcher> mWWatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); |
|
|
if (mWWatch) { |
|
|
nsCOMPtr<nsIWebBrowserChrome> chrome; |
|
|
CWnd *val = 0; |
|
|
|
|
|
nsCOMPtr<nsIDOMWindow> fosterParent; |
|
|
mWWatch->GetChromeForWindow(mDomWindow, getter_AddRefs(chrome)); |
|
|
if (chrome) |
|
|
chrome->DestroyBrowserWindow(); |
|
|
} |
|
|
} |
|
|
|
|
|
return rv; |
|
|
} |
|
|
|
|
|
// Show the helper app launch confirmation dialog as instructed. |
|
|
NS_IMETHODIMP |
|
|
CUnknownContentTypeHandler::Show( nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRUint32 aReason) |
|
|
{ |
|
|
NS_ENSURE_ARG_POINTER(aLauncher); |
|
|
mAppLauncher = aLauncher; |
|
|
|
|
|
// This function must return immediately or all transferts are stalled. |
|
|
// XXX: Stupid mozilla |
|
|
// If an error happen (ex: temporary folder is full), an error message |
|
|
// is show to the user when asking to open/save or for the location. |
|
|
// The dialogs asking open/save or for the location must be closed at |
|
|
// the same time than the error message. |
|
|
|
|
|
mDomWindow = do_GetInterface (aContext); |
|
|
CWnd* wnd = CWndForDOMWindow(mDomWindow); |
|
|
|
|
|
theApp.m_pMainWnd->PostMessage(WM_DEFERSHOW, (WPARAM)wnd, (LPARAM)this); |
|
|
|
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CUnknownContentTypeHandler::PromptForSaveToFileAsync(nsIHelperAppLauncher *aLauncher, nsISupports *aWindowContext, const PRUnichar * aDefaultFileName, const PRUnichar * aSuggestedFileExtension, bool aForcePrompt) |
|
|
{ |
|
|
return NS_ERROR_NOT_IMPLEMENTED; |
|
|
} |
|
|
#if 0 |
|
|
// prompt the user for a file name to save the unknown content to as instructed |
|
|
NS_IMETHODIMP |
|
|
CUnknownContentTypeHandler::PromptForSaveToFile(nsIHelperAppLauncher *aLauncher, nsISupports *aWindowContext, const PRUnichar * aDefaultFile, const PRUnichar * aSuggestedFileExtension, bool aForcePrompt, nsIFile * *aNewFile) |
|
|
{ |
|
|
NS_ENSURE_ARG_POINTER(aNewFile); |
|
|
NS_ENSURE_ARG(aDefaultFile); |
|
|
NS_ENSURE_ARG(aSuggestedFileExtension); |
|
|
|
|
|
// change this to 0 to use the mozilla file picker |
|
|
#if 1 |
|
|
USES_CONVERSION; |
|
|
|
|
|
CString pathName; |
|
|
|
|
|
CString downloadDir = theApp.preferences.downloadDir; |
|
|
if (theApp.preferences.bUseDownloadDir && !downloadDir.IsEmpty() |
|
|
&& !aForcePrompt |
|
|
) |
|
|
{ |
|
|
if (downloadDir[downloadDir.GetLength()-1] != '\\') |
|
|
downloadDir += '\\'; |
|
|
pathName = downloadDir + PRUnicharToCString(aDefaultFile); |
|
|
} |
|
|
else |
|
|
{ |
|
|
CString defaultFile = (CString)theApp.preferences.lastDownloadDir + PRUnicharToCString(aDefaultFile); |
|
|
CString fileType; |
|
|
|
|
|
CString filter; |
|
|
const TCHAR *ext = _T(""); |
|
|
if (*aSuggestedFileExtension) { |
|
|
|
|
|
fileType = GetTypeName(); |
|
|
|
|
|
if (!fileType.IsEmpty()) |
|
|
filter = fileType; |
|
|
else { |
|
|
filter = _T("*"); |
|
|
filter += W2CT(aSuggestedFileExtension); |
|
|
} |
|
|
filter += _T("|*"); |
|
|
filter += W2CT(aSuggestedFileExtension); |
|
|
filter += _T("|"); |
|
|
|
|
|
ext = W2CT(aSuggestedFileExtension+1); |
|
|
} |
|
|
|
|
|
filter += _T("All Files|*.*||"); |
|
|
|
|
|
TCHAR lpszFilter[1024]; |
|
|
_tcscpy(lpszFilter, filter); |
|
|
for (int i=0; lpszFilter[i]; ) { |
|
|
if (lpszFilter[i] == _T('|')) |
|
|
lpszFilter[i] = _T('\0'); |
|
|
i++; |
|
|
} |
|
|
|
|
|
OPENFILENAME ofn; |
|
|
TCHAR *szFileName = new TCHAR[INTERNET_MAX_URL_LENGTH]; |
|
|
|
|
|
memset(&ofn, 0, sizeof(ofn)); |
|
|
memset(szFileName, 0, sizeof(TCHAR)*INTERNET_MAX_URL_LENGTH); |
|
|
_tcscat(szFileName, defaultFile); |
|
|
ofn.lStructSize = sizeof(ofn); |
|
|
ofn.lpstrFilter = lpszFilter; |
|
|
ofn.lpstrFile = szFileName; |
|
|
ofn.nMaxFile = INTERNET_MAX_URL_LENGTH; |
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; |
|
|
ofn.lpstrInitialDir = theApp.preferences.lastDownloadDir; |
|
|
ofn.lpstrDefExt = ext; |
|
|
|
|
|
BOOL bGetFile; |
|
|
if( !(bGetFile=::GetSaveFileName(&ofn)) ) |
|
|
{ |
|
|
// Fix: If the download dir contains invalid character, it'll |
|
|
// never show up |
|
|
if (CommDlgExtendedError() == FNERR_INVALIDFILENAME) |
|
|
{ |
|
|
_tcscpy(szFileName, W2CT(aDefaultFile)); |
|
|
theApp.preferences.lastDownloadDir = _T(""); |
|
|
bGetFile = ::GetSaveFileName(&ofn); |
|
|
} |
|
|
} |
|
|
if (bGetFile) |
|
|
pathName = szFileName; |
|
|
|
|
|
delete [] szFileName; |
|
|
szFileName = NULL; |
|
|
} |
|
|
|
|
|
if (!pathName.IsEmpty()) |
|
|
{ |
|
|
nsCOMPtr<nsIFile> file(do_CreateInstance("@mozilla.org/file/local;1")); |
|
|
|
|
|
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE); |
|
|
|
|
|
#ifdef _UNICODE |
|
|
nsresult rv = file->InitWithPath(nsDependentString(pathName)); |
|
|
#else |
|
|
nsresult rv = file->InitWithNativePath(nsDependentCString(pathName)); |
|
|
#endif |
|
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); |
|
|
|
|
|
NS_ADDREF(*aNewFile = file); |
|
|
|
|
|
// Be sure to save off the new default saveDir |
|
|
int slash = pathName.ReverseFind('\\'); |
|
|
if (slash == -1) { |
|
|
pathName.ReverseFind('/'); |
|
|
} |
|
|
if (slash != -1) { |
|
|
theApp.preferences.lastDownloadDir = pathName.Left(slash+1); |
|
|
} |
|
|
|
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
return NS_ERROR_FAILURE; |
|
|
#else |
|
|
|
|
|
nsresult rv = NS_OK; |
|
|
|
|
|
nsCOMPtr<nsIFilePicker> filePicker = do_CreateInstance("@mozilla.org/filepicker;1"); |
|
|
// nsCOMPtr<nsIFilePicker> filePicker = do_CreateInstance(NS_FILEPICKER_CID, &rv); |
|
|
if (filePicker) |
|
|
{ |
|
|
nsString title = NS_LITERAL_STRING ("Save As:"); |
|
|
|
|
|
nsCOMPtr<nsIDOMWindowInternal> parent( do_GetInterface( aWindowContext ) ); |
|
|
filePicker->Init(parent, title, nsIFilePicker::modeSave); |
|
|
filePicker->SetDefaultString(nsDependentString(aDefaultFile)); |
|
|
nsString wildCardExtension (NS_LITERAL_STRING("*").get()); |
|
|
if (aSuggestedFileExtension) { |
|
|
wildCardExtension.Append(aSuggestedFileExtension); |
|
|
filePicker->AppendFilter(wildCardExtension, wildCardExtension); |
|
|
} |
|
|
|
|
|
filePicker->AppendFilters(nsIFilePicker::filterAll); |
|
|
|
|
|
nsCOMPtr<nsILocalFile> startDir; |
|
|
// Pull in the user's preferences and get the default download directory. |
|
|
nsCOMPtr<nsIPref> prefs (do_GetService(NS_PREF_CONTRACTID)); |
|
|
if ( prefs ) |
|
|
{ |
|
|
rv = prefs->GetFileXPref( "browser.download.dir", getter_AddRefs( startDir ) ); |
|
|
if ( NS_SUCCEEDED(rv) && startDir ) |
|
|
{ |
|
|
PRBool isValid = PR_FALSE; |
|
|
startDir->Exists( &isValid ); |
|
|
if ( isValid ) // Set file picker so startDir is used. |
|
|
filePicker->SetDisplayDirectory( startDir ); |
|
|
} |
|
|
} |
|
|
|
|
|
PRInt16 dialogResult; |
|
|
filePicker->Show(&dialogResult); |
|
|
if (dialogResult == nsIFilePicker::returnCancel) |
|
|
rv = NS_ERROR_FAILURE; |
|
|
else |
|
|
{ |
|
|
// be sure to save the directory the user chose as the new browser.download.dir |
|
|
rv = filePicker->GetFile(aNewFile); |
|
|
if (*aNewFile) |
|
|
{ |
|
|
nsCOMPtr<nsIFile> newDirectory; |
|
|
(*aNewFile)->GetParent(getter_AddRefs(newDirectory)); |
|
|
nsCOMPtr<nsILocalFile> newLocalDirectory (do_QueryInterface(newDirectory)); |
|
|
|
|
|
if (newLocalDirectory) |
|
|
prefs->SetFileXPref( "browser.download.dir", newLocalDirectory); |
|
|
} |
|
|
} |
|
|
} |
|
|
return rv; |
|
|
|
|
|
/* |
|
|
USES_CONVERSION; |
|
|
NS_ENSURE_ARG_POINTER(aNewFile); |
|
|
char *lpszFilter = "All Files (*.*)|*.*||"; |
|
|
CFileDialog cf(FALSE, W2T(aSuggestedFileExtension), W2T(aDefaultFile), |
|
|
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, |
|
|
lpszFilter, NULL); |
|
|
if(cf.DoModal() == IDOK) |
|
|
{ |
|
|
CString m_FileName = cf.GetPathName(); // Will be like: c:\tmp\junk.exe |
|
|
|
|
|
return NS_NewLocalFile(m_FileName, PR_FALSE, aNewFile); |
|
|
} |
|
|
else |
|
|
return NS_ERROR_FAILURE; |
|
|
*/ |
|
|
|
|
|
#endif |
|
|
} |
|
|
#endif |
|
|
|
|
|
CString CUnknownContentTypeHandler::GetTypeName() |
|
|
{ |
|
|
USES_CONVERSION; |
|
|
nsresult rv; |
|
|
|
|
|
nsCOMPtr<nsIMIMEInfo> mimeInfo; |
|
|
mAppLauncher->GetMIMEInfo(getter_AddRefs(mimeInfo)); |
|
|
|
|
|
if(mimeInfo) |
|
|
{ |
|
|
nsCString mimeType; |
|
|
rv = mimeInfo->GetMIMEType(mimeType); |
|
|
nsString mimeDesc; |
|
|
rv = mimeInfo->GetDescription(mimeDesc); |
|
|
if(NS_SUCCEEDED(rv)) { |
|
|
if (*mimeDesc.get()) |
|
|
return CString(W2CA(mimeDesc.get())); |
|
|
if (*mimeType.get()) |
|
|
return CString(A2CT(mimeType.get())); |
|
|
} |
|
|
} |
|
|
|
|
|
nsString filename; |
|
|
mAppLauncher->GetSuggestedFileName(filename); |
|
|
SHFILEINFO shfi = {0}; |
|
|
if (SHGetFileInfo(W2CT(filename.get()), 0, &shfi, sizeof(SHFILEINFO),SHGFI_USEFILEATTRIBUTES|SHGFI_TYPENAME)) |
|
|
return CString(shfi.szTypeName); |
|
|
return CString(); |
|
|
} |
|
|
|
|
|
/* -- Mark L.: Leftover from a forgotten era? |
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(CUnknownContentTypeHandler) |
|
|
|
|
|
static nsModuleComponentInfo components[] = { |
|
|
{ NS_IHELPERAPPLAUNCHERDLG_CLASSNAME, |
|
|
NS_UNKNOWNCONTENTTYPEHANDLER_CID, |
|
|
NS_IHELPERAPPLAUNCHERDLG_CONTRACTID, |
|
|
CUnknownContentTypeHandlerConstructor }, |
|
|
}; |
|
|
|
|
|
NS_IMPL_NSGETMODULE("CUnknownContentTypeHandler", components ) |
|
|
*/ |
|
|
|
|
|
/* nsISupports Implementation for the class */ |
|
|
NS_IMPL_ISUPPORTS(CUnknownContentTypeHandler, nsIHelperAppLauncherDialog, nsIContentHandler) |
|
|
|
|
|
|
|
|
//***************************************************************************** |
|
|
// CUnknownContentHandlerFactory |
|
|
//***************************************************************************** |
|
|
|
|
|
class CUnknownContentHandlerFactory : public nsIFactory |
|
|
{ |
|
|
public: |
|
|
NS_DECL_ISUPPORTS |
|
|
NS_DECL_NSIFACTORY |
|
|
|
|
|
CUnknownContentHandlerFactory(); |
|
|
virtual ~CUnknownContentHandlerFactory(); |
|
|
}; |
|
|
|
|
|
//***************************************************************************** |
|
|
/* |
|
|
NS_IMPL_ISUPPORTS1(CUnknownContentHandlerFactory, nsIFactory) |
|
|
|
|
|
CUnknownContentHandlerFactory::CUnknownContentHandlerFactory() |
|
|
{ |
|
|
NS_INIT_ISUPPORTS(); |
|
|
} |
|
|
|
|
|
CUnknownContentHandlerFactory::~CUnknownContentHandlerFactory() |
|
|
{ |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CUnknownContentHandlerFactory::CreateInstance(nsISupports *aOuter, const nsIID & aIID, void **aResult) |
|
|
{ |
|
|
NS_ENSURE_ARG_POINTER(aResult); |
|
|
|
|
|
*aResult = NULL; |
|
|
CUnknownContentTypeHandler *inst = new CUnknownContentTypeHandler; |
|
|
if (!inst) |
|
|
return NS_ERROR_OUT_OF_MEMORY; |
|
|
|
|
|
nsresult rv = inst->QueryInterface(aIID, aResult); |
|
|
if (rv != NS_OK) { |
|
|
// We didn't get the right interface, so clean up |
|
|
delete inst; |
|
|
} |
|
|
|
|
|
return rv; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CUnknownContentHandlerFactory::LockFactory(PRBool lock) |
|
|
{ |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
|
|
|
nsresult NewUnknownContentHandlerFactory(nsIFactory** aFactory) { |
|
|
NS_ENSURE_ARG_POINTER(aFactory); |
|
|
*aFactory = nullptr; |
|
|
CUnknownContentHandlerFactory *result = new CUnknownContentHandlerFactory; |
|
|
if (!result) |
|
|
return NS_ERROR_OUT_OF_MEMORY; |
|
|
NS_ADDREF(result); |
|
|
*aFactory = result; |
|
|
return NS_OK; |
|
|
} |
|
|
*/ |
|
|
|
|
|
/******************************************************************************************************** |
|
|
file save progress dialog box |
|
|
********************************************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
23 October, 2002 |
|
|
|
|
|
This class needs to be entirely reworked, it's pretty much a gross hack to |
|
|
get us just what we need at the moment, when it's cleaned up, we'll actually |
|
|
be able to do some better stuff. We need an implementation that supports: |
|
|
|
|
|
1) automatic (factory) downloads |
|
|
2) manual (save link as) downloads |
|
|
3) behind-the-scenes (view-source) downloads, with some sort of "file complete" callback or flag |
|
|
|
|
|
-- Jeff |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
// WeakReference not needed? |
|
|
//NS_IMPL_ISUPPORTS3(CProgressDialog, nsITransfer, nsIWebProgressListener2, nsIWebProgressListener) |
|
|
NS_IMPL_ISUPPORTS(CProgressDialog, nsITransfer, nsIWebProgressListener2, nsIWebProgressListener, nsISupportsWeakReference) |
|
|
|
|
|
CProgressDialog::CProgressDialog(BOOL bAuto) { |
|
|
|
|
|
//mObserver = NULL; |
|
|
mCancelable = nullptr; |
|
|
m_HelperAppLauncher = nullptr; |
|
|
mMIMEInfo = nullptr; |
|
|
mTempFile = nullptr; |
|
|
mTarget = nullptr; |
|
|
mStartTime = 0; |
|
|
mPaused = FALSE; |
|
|
|
|
|
m_HandleContentOp = 0; |
|
|
|
|
|
// assume we're done until we get data |
|
|
// for small files, we'll be done before the box even pops up |
|
|
// mDone = true; |
|
|
mDone = false; |
|
|
mTotalBytes = 0; |
|
|
|
|
|
m_bClose = theApp.preferences.bCloseDownloadDialog; |
|
|
|
|
|
// the instance was created automatically by a download |
|
|
// if it's false, then we can expect an Attach() call to bind this to a persist object |
|
|
// if it's true, then we'll pop up the download dialog here |
|
|
/* m_bAuto = bAuto; |
|
|
if (m_bAuto) { |
|
|
m_bWindow = TRUE; |
|
|
Create(IDD_PROGRESS, GetDesktopWindow()); |
|
|
CheckDlgButton(IDC_CLOSE_WHEN_DONE, TRUE); |
|
|
GetDlgItem(IDC_CLOSE_WHEN_DONE)->EnableWindow(FALSE); |
|
|
theApp.RegisterWindow(this); |
|
|
} |
|
|
else*/ |
|
|
m_bWindow = FALSE; |
|
|
mUri = NULL; |
|
|
|
|
|
mCallback = NULL; |
|
|
mParam = NULL; |
|
|
} |
|
|
|
|
|
CProgressDialog::~CProgressDialog(){ |
|
|
if (mUri) |
|
|
delete mUri; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CProgressDialog::OnProgressChange64(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt64 aCurSelfProgress, PRInt64 aMaxSelfProgress, PRInt64 aCurTotalProgress, PRInt64 aMaxTotalProgress) |
|
|
{ |
|
|
if (!mTotalBytes) |
|
|
mTotalBytes = aMaxTotalProgress; |
|
|
|
|
|
if (!mRequest) { |
|
|
mRequest = aRequest; |
|
|
CWnd* button = GetDlgItem(IDC_PAUSE); |
|
|
if (button) |
|
|
button->ShowWindow(SW_SHOW); |
|
|
} |
|
|
/* |
|
|
|
|
|
if (aMaxTotalProgress <= 0) |
|
|
return NS_OK; |
|
|
else if (!mTotalBytes) |
|
|
// strangely enough, this isn't a parameter in nsIDownload::Init() |
|
|
mTotalBytes = aMaxTotalProgress; |
|
|
|
|
|
if (!m_bWindow) // if there's no window, there's no need to update it :) |
|
|
return NS_OK; |
|
|
|
|
|
if (mStartTime <= 0) |
|
|
return NS_OK; |
|
|
*/ |
|
|
|
|
|
if (!m_bWindow) // if there's no window, there's no need to update it :) |
|
|
return NS_OK; |
|
|
|
|
|
|
|
|
if (aMaxTotalProgress && ( |
|
|
PRNow() > mLastUpdateTime + 100000.0l // enforce a minimum delay between updates - gives a large speed increase for super-fast downloads which wasted CPU cycles updating the dialog constantly |
|
|
|| aCurTotalProgress >= aMaxTotalProgress // and be sure to catch the very last one, in case it would otherwise be skipped by the time check |
|
|
) ) |
|
|
{ |
|
|
mLastUpdateTime = PRNow(); |
|
|
mDone = false; |
|
|
|
|
|
int percent = (int)(((float)aCurTotalProgress / (float)aMaxTotalProgress) * 100.0f); |
|
|
|
|
|
CString progressString; |
|
|
if (percent>=0 && percent<=100) |
|
|
progressString.Format(IDS_DOWNLOAD_PROGRESS, percent, ((double)aCurTotalProgress)/1024, ((double)aMaxTotalProgress)/1024); |
|
|
else |
|
|
progressString.Format(IDS_DOWNLOAD_PROGRESS2, ((double)aCurTotalProgress)/1024); |
|
|
SetDlgItemText(IDC_STATUS, progressString); |
|
|
|
|
|
PRInt64 now = PRNow(); |
|
|
PRInt64 timeSpent = now - mStartTime; |
|
|
PRInt64 delta = aCurTotalProgress; |
|
|
|
|
|
// given in bytes per second! |
|
|
double speed = 0.0; |
|
|
|
|
|
double timeSpent_seconds = ((double)timeSpent/1000000.0l); |
|
|
if (timeSpent_seconds > 0) |
|
|
speed = delta / timeSpent_seconds; |
|
|
|
|
|
double speed_kbs = speed/1024; |
|
|
|
|
|
CString speedString; |
|
|
speedString.Format(IDS_SPEED_STRING, speed_kbs); |
|
|
SetDlgItemText(IDC_SPEED, speedString); |
|
|
|
|
|
if (speed) { |
|
|
PRInt32 remaining = (PRInt32)((aMaxTotalProgress - aCurTotalProgress)/speed +.5); |
|
|
|
|
|
CString timeString; |
|
|
|
|
|
if (remaining >= 0) { |
|
|
int remainHours=0, remainMin=0, remainSec=0, remainTemp; |
|
|
remainTemp = remaining; |
|
|
|
|
|
if (remainTemp > 3600) { |
|
|
remainHours = remainTemp/3600; |
|
|
remainTemp %= 3600; |
|
|
} |
|
|
if (remainTemp > 60) { |
|
|
remainMin = remainTemp/60; |
|
|
remainTemp %= 60; |
|
|
} |
|
|
remainSec = remainTemp; |
|
|
|
|
|
if (remainHours) |
|
|
timeString.Format(IDS_TIMELEFT_HOURS, remainHours, remainMin, remainSec); |
|
|
else if (remainMin) { |
|
|
if (remainMin == 1) |
|
|
timeString.Format(IDS_TIMELEFT_MINUTE, remainSec); |
|
|
else |
|
|
timeString.Format(IDS_TIMELEFT_MINUTES, remainMin, remainSec); |
|
|
} |
|
|
else |
|
|
timeString.Format(IDS_TIMELEFT_SECONDS, remainSec); |
|
|
} |
|
|
else |
|
|
timeString.Format(IDS_TIMELEFT_UNKNOWN); |
|
|
SetDlgItemText(IDC_TIME_LEFT, timeString); |
|
|
} |
|
|
|
|
|
if (percent>=0 && percent<=100) { |
|
|
CString titleString; |
|
|
titleString.Format(IDS_PERCENT_OF_FILE, percent, mFileName); |
|
|
SetWindowText(titleString); |
|
|
} |
|
|
else |
|
|
SetWindowText(mFileName); |
|
|
|
|
|
|
|
|
HWND progressBar; |
|
|
GetDlgItem(IDC_DOWNLOAD_PROGRESS, &progressBar); |
|
|
::SendMessage(progressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); |
|
|
::SendMessage(progressBar, PBM_SETPOS, (WPARAM) percent, 0); |
|
|
} |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
nsresult CProgressDialog::GetTargetFile(nsIFile **aTargetFile) |
|
|
{ |
|
|
nsresult rv; |
|
|
|
|
|
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget, &rv); |
|
|
if (NS_FAILED(rv)) { |
|
|
return rv; |
|
|
} |
|
|
|
|
|
nsCOMPtr<nsIFile> file; |
|
|
rv = fileURL->GetFile(getter_AddRefs(file)); |
|
|
if (NS_FAILED(rv)) { |
|
|
return rv; |
|
|
} |
|
|
|
|
|
file.forget(aTargetFile); |
|
|
return rv; |
|
|
} |
|
|
|
|
|
|
|
|
nsresult CProgressDialog::MoveTempToTarget() |
|
|
{ |
|
|
nsCOMPtr<nsIFile> target; |
|
|
nsresult rv = GetTargetFile(getter_AddRefs(target)); |
|
|
NS_ENSURE_SUCCESS(rv, rv); |
|
|
|
|
|
// MoveTo will fail if the file already exists, but we've already obtained |
|
|
// confirmation from the user that this is OK, so remove it if it exists. |
|
|
bool fileExists; |
|
|
if (NS_SUCCEEDED(target->Exists(&fileExists)) && fileExists) { |
|
|
rv = target->Remove(false); |
|
|
NS_ENSURE_SUCCESS(rv, rv); |
|
|
} |
|
|
|
|
|
// Extract the new leaf name from the file location |
|
|
nsAutoString fileName; |
|
|
rv = target->GetLeafName(fileName); |
|
|
NS_ENSURE_SUCCESS(rv, rv); |
|
|
nsCOMPtr<nsIFile> dir; |
|
|
rv = target->GetParent(getter_AddRefs(dir)); |
|
|
NS_ENSURE_SUCCESS(rv, rv); |
|
|
rv = mTempFile->MoveTo(dir, fileName); |
|
|
NS_ENSURE_SUCCESS(rv, rv); |
|
|
|
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
nsresult CProgressDialog::OpenWithApplication() |
|
|
{ |
|
|
// First move the temporary file to the target location |
|
|
nsCOMPtr<nsIFile> target; |
|
|
nsresult rv = GetTargetFile(getter_AddRefs(target)); |
|
|
NS_ENSURE_SUCCESS(rv, rv); |
|
|
|
|
|
// Move the temporary file to the target location |
|
|
rv = MoveTempToTarget(); |
|
|
NS_ENSURE_SUCCESS(rv, rv); |
|
|
|
|
|
// We do not verify the return value here because, irrespective of success |
|
|
// or failure of the method, the deletion of temp file has to take place, as |
|
|
// per the corresponding preference. But we store this separately as this is |
|
|
// what we ultimately return from this function. |
|
|
nsresult retVal = mMIMEInfo->LaunchWithFile(target); |
|
|
|
|
|
bool deleteTempFileOnExit = true; |
|
|
/* nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); |
|
|
if (!prefs || NS_FAILED(prefs->GetBoolPref(PREF_BH_DELETETEMPFILEONEXIT, |
|
|
&deleteTempFileOnExit))) { |
|
|
// No prefservice or no pref set; use default value |
|
|
#if !defined(XP_MACOSX) |
|
|
// Mac users have been very verbal about temp files being deleted on |
|
|
// app exit - they don't like it - but we'll continue to do this on |
|
|
// other platforms for now. |
|
|
deleteTempFileOnExit = true; |
|
|
#else |
|
|
deleteTempFileOnExit = false; |
|
|
#endif |
|
|
}*/ |
|
|
|
|
|
// Always schedule files to be deleted at the end of the private browsing |
|
|
// mode, regardless of the value of the pref. |
|
|
if (deleteTempFileOnExit) { |
|
|
// Use the ExternalHelperAppService to push the temporary file to the list |
|
|
// of files to be deleted on exit. |
|
|
nsCOMPtr<nsPIExternalAppLauncher> appLauncher(do_GetService |
|
|
(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID)); |
|
|
|
|
|
// Even if we are unable to get this service we return the result |
|
|
// of LaunchWithFile() which makes more sense. |
|
|
if (appLauncher) { |
|
|
//if (mPrivate) { |
|
|
// (void)appLauncher->DeleteTemporaryPrivateFileWhenPossible(target); |
|
|
// } else { |
|
|
(void)appLauncher->DeleteTemporaryFileOnExit(target); |
|
|
// } |
|
|
} |
|
|
} |
|
|
|
|
|
return retVal; |
|
|
} |
|
|
|
|
|
|
|
|
nsresult CProgressDialog::ExecuteDesiredAction() |
|
|
{ |
|
|
if (!mMIMEInfo) |
|
|
return NS_OK; |
|
|
|
|
|
nsHandlerInfoAction action = nsIMIMEInfo::saveToDisk; |
|
|
if (mMIMEInfo) { |
|
|
nsresult rv = mMIMEInfo->GetPreferredAction(&action); |
|
|
NS_ENSURE_SUCCESS(rv, rv); |
|
|
} |
|
|
|
|
|
nsresult retVal = NS_OK; |
|
|
switch (action) { |
|
|
case nsIMIMEInfo::saveToDisk: |
|
|
// Move the file to the proper location |
|
|
retVal = MoveTempToTarget(); |
|
|
break; |
|
|
case nsIMIMEInfo::useHelperApp: |
|
|
case nsIMIMEInfo::useSystemDefault: |
|
|
// For these cases we have to move the file to the target location and |
|
|
// open with the appropriate application |
|
|
retVal = OpenWithApplication(); |
|
|
break; |
|
|
default: |
|
|
break; |
|
|
} |
|
|
|
|
|
return retVal; |
|
|
} |
|
|
|
|
|
/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aStateFlags, in unsigned long aStatus); */ |
|
|
NS_IMETHODIMP CProgressDialog::OnStateChange(nsIWebProgress *aWebProgress, |
|
|
nsIRequest *aRequest, PRUint32 aStateFlags, |
|
|
nsresult aStatus) |
|
|
{ |
|
|
if (aStateFlags & nsIWebProgressListener::STATE_START && |
|
|
aStateFlags & nsIWebProgressListener::STATE_IS_REQUEST) |
|
|
{ |
|
|
// Failing on a http error instead of downloading an erroneous file |
|
|
nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface(aRequest); |
|
|
if (httpchannel) |
|
|
{ |
|
|
bool b; |
|
|
nsresult rv = httpchannel->GetRequestSucceeded(&b); |
|
|
if (NS_SUCCEEDED(rv) && b == PR_FALSE) { |
|
|
Cancel(); |
|
|
return NS_OK; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
CString statusText; |
|
|
|
|
|
if ( (aStateFlags & nsIWebProgressListener::STATE_STOP)) |
|
|
{ |
|
|
if (mCallback) |
|
|
mCallback(mUri, (LPTSTR)(LPCTSTR)mFilePath, aStatus, mParam); |
|
|
|
|
|
//nsCOMPtr<nsITransfer> kungFuDeathGrip(this); |
|
|
mCancelable = nullptr; |
|
|
|
|
|
if (!m_bWindow) // if there's no window, there's no need to update it :) |
|
|
return NS_OK; |
|
|
|
|
|
if (NS_SUCCEEDED(aStatus)) { |
|
|
|
|
|
if (mMIMEInfo) ExecuteDesiredAction(); //XXXX |
|
|
|
|
|
if (IsDlgButtonChecked(IDC_CLOSE_WHEN_DONE)) { |
|
|
if (!m_bAuto) |
|
|
theApp.preferences.bCloseDownloadDialog = true; |
|
|
Close(); |
|
|
} |
|
|
else |
|
|
{ |
|
|
PRInt64 now = PRNow(); |
|
|
PRInt64 timeSpent = now - mStartTime; |
|
|
statusText.Format(IDS_DOWNLOAD_DONE, ((double)mTotalBytes)/1024, (int)(timeSpent/1000000.0l)); |
|
|
|
|
|
// "save link as..." saving never gets the final progress change, |
|
|
// which leaves the progress bar hanging around 90% or so |
|
|
HWND progressBar; |
|
|
GetDlgItem(IDC_DOWNLOAD_PROGRESS, &progressBar); |
|
|
::SendMessage(progressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); |
|
|
::SendMessage(progressBar, PBM_SETPOS, (WPARAM) 100, 0); |
|
|
|
|
|
SetDlgItemText(IDC_STATUS, statusText); |
|
|
|
|
|
statusText.LoadString(IDS_CLOSE); |
|
|
SetDlgItemText(IDCANCEL, statusText); |
|
|
|
|
|
if (m_HandleContentOp!=1) { |
|
|
GetDlgItem(IDC_OPEN)->ShowWindow(SW_SHOW); |
|
|
CWnd* button = GetDlgItem(IDC_OPENFOLDER); |
|
|
if (button) button->ShowWindow(SW_SHOW); |
|
|
GetDlgItem(IDC_CLOSE_WHEN_DONE)->ShowWindow(SW_HIDE); |
|
|
} |
|
|
|
|
|
CWnd* button = GetDlgItem(IDC_PAUSE); |
|
|
if (button) button->ShowWindow(SW_HIDE); |
|
|
|
|
|
mDone = true; |
|
|
mRequest = nullptr; |
|
|
theApp.preferences.bCloseDownloadDialog = false; |
|
|
|
|
|
if (theApp.preferences.bFlashWhenCompleted) |
|
|
FlashWindow(TRUE); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
statusText.LoadString(IDS_DOWNLOAD_FAILED); |
|
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface(aRequest); |
|
|
if (httpchannel) |
|
|
{ |
|
|
bool b; |
|
|
nsresult rv = httpchannel->GetRequestSucceeded(&b); |
|
|
if (NS_SUCCEEDED(rv) && b == PR_FALSE) { |
|
|
nsCString str; |
|
|
httpchannel->GetResponseStatusText(str); |
|
|
// Fix me : text can be encoded in anything |
|
|
#ifdef UNICODE |
|
|
nsString _str; |
|
|
NS_CStringToUTF16(str, NS_CSTRING_ENCODING_ASCII, _str); |
|
|
statusText += _str.get(); |
|
|
#else |
|
|
statusText += str.get(); |
|
|
#endif |
|
|
statusText += _T("!"); |
|
|
} |
|
|
|
|
|
} |
|
|
if (m_bWindow) { |
|
|
SetDlgItemText(IDC_STATUS, statusText); |
|
|
GetDlgItem(IDC_CLOSE_WHEN_DONE)->ShowWindow(SW_HIDE); |
|
|
statusText.LoadString(IDS_CLOSE); |
|
|
SetDlgItemText(IDCANCEL, statusText); |
|
|
} |
|
|
|
|
|
mDone = true; |
|
|
if (theApp.preferences.bFlashWhenCompleted) |
|
|
FlashWindow(TRUE); |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (!m_bWindow) |
|
|
return NS_OK; |
|
|
|
|
|
if (aStateFlags & nsIWebProgressListener::STATE_REDIRECTING){ |
|
|
statusText.LoadString(IDS_REDIRECTING); |
|
|
SetDlgItemText(IDC_STATUS, statusText); |
|
|
}else if (aStateFlags & nsIWebProgressListener::STATE_TRANSFERRING){ |
|
|
statusText.LoadString(IDS_DOWNLOADING); |
|
|
SetDlgItemText(IDC_STATUS, statusText); |
|
|
}else if (aStateFlags & nsIWebProgressListener::STATE_NEGOTIATING){ |
|
|
statusText.LoadString(IDS_NEGOTIATING); |
|
|
SetDlgItemText(IDC_STATUS, statusText); |
|
|
}else if (aStateFlags & nsIWebProgressListener::STATE_START){ |
|
|
// Since fix for BUG #752 the download can be finished before the |
|
|
// progress dialog is created. In that case, mozilla send a |
|
|
// STATE_START after a STATE_STOP ... |
|
|
if (!mDone) { |
|
|
statusText.LoadString(IDS_CONTACTING); |
|
|
SetDlgItemText(IDC_STATUS, statusText); |
|
|
} |
|
|
} |
|
|
|
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ |
|
|
NS_IMETHODIMP CProgressDialog::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) |
|
|
{ |
|
|
return OnProgressChange64(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress); |
|
|
} |
|
|
|
|
|
/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ |
|
|
NS_IMETHODIMP CProgressDialog::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *aLocation, uint32_t aFlags) { |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ |
|
|
NS_IMETHODIMP CProgressDialog::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage){ |
|
|
USES_CONVERSION; |
|
|
Cancel(); |
|
|
::AfxMessageBox(W2CT(aMessage),MB_OK|MB_ICONEXCLAMATION); |
|
|
if (m_bWindow) |
|
|
Close(); |
|
|
/*MessageBox(W2CA(aMessage), "", MB_OK|MB_ICONERROR); |
|
|
if (m_bWindow) |
|
|
{ |
|
|
CString statusText; |
|
|
USES_CONVERSION; |
|
|
statusText = W2CA(aMessage); |
|
|
SetDlgItemText(IDC_STATUS, statusText); |
|
|
}*/ |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CProgressDialog::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) |
|
|
{ |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CProgressDialog::SetSignatureInfo(nsIArray *aSignatureInfo) |
|
|
{ |
|
|
return NS_ERROR_NOT_IMPLEMENTED; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// We're overriding a function with... itself? |
|
|
//void CProgressDialog::DoDataExchange(CDataExchange* pDX){ |
|
|
// CDialog::DoDataExchange(pDX); |
|
|
//} |
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CProgressDialog, CDialog) |
|
|
ON_COMMAND(IDC_OPEN, OnOpen) |
|
|
ON_COMMAND(IDC_PAUSE, OnPause) |
|
|
ON_COMMAND(IDC_OPENFOLDER, OnOpenFolder) |
|
|
ON_COMMAND(WM_CLOSE, OnClose) |
|
|
ON_BN_CLICKED(IDC_CLOSE_WHEN_DONE, OnBnClickedCloseWhenDone) |
|
|
ON_WM_QUERYENDSESSION() |
|
|
END_MESSAGE_MAP() |
|
|
|
|
|
void CProgressDialog::Cancel() { |
|
|
|
|
|
if (mCancelable) |
|
|
{ |
|
|
mCancelable->Cancel(NS_BINDING_ABORTED); |
|
|
bool tempExists; |
|
|
if (mTempFile && NS_SUCCEEDED(mTempFile->Exists(&tempExists)) && tempExists) |
|
|
mTempFile->Remove(false); |
|
|
//if (mTempFile.GetLength()) |
|
|
// DeleteFile(mTempFile); |
|
|
else if (mFileName.GetLength()) |
|
|
DeleteFile(mFileName); |
|
|
} |
|
|
else |
|
|
if (mFileName.GetLength()) DeleteFile(mFileName); |
|
|
|
|
|
// Connection is not correctly closed when download |
|
|
// is in pause. This fix it. // XXX MOZILLA |
|
|
if (mRequest) |
|
|
mRequest->Cancel(NS_BINDING_ABORTED); |
|
|
|
|
|
//Close(); |
|
|
|
|
|
/* if (mObserver) { |
|
|
mObserver->Observe(nullptr, "OnCancel", nullptr); |
|
|
mObserver->Observe(nullptr, "oncancel", nullptr); |
|
|
}*/ |
|
|
} |
|
|
|
|
|
void CProgressDialog::Close() { |
|
|
|
|
|
theApp.UnregisterWindow(this); |
|
|
DestroyWindow(); |
|
|
|
|
|
m_bWindow = false; |
|
|
|
|
|
/* if (mCancelable) |
|
|
mCancelable = nullptr;*/ |
|
|
|
|
|
NS_RELEASE_THIS(); |
|
|
/* |
|
|
// Not needed, mozilla have corrected the bug |
|
|
if (m_bAuto) { |
|
|
// we need launcher to call CloseProgressWindow() and be properly disposed |
|
|
nsresult rv; |
|
|
nsCOMPtr<nsIHelperAppLauncher> launcher( do_QueryInterface(mObserver, &rv) ); |
|
|
if (rv == NS_OK) { |
|
|
launcher->CloseProgressWindow(); |
|
|
} |
|
|
}*/ |
|
|
|
|
|
} |
|
|
|
|
|
void CProgressDialog::OnOpenFolder() |
|
|
{ |
|
|
CString directory = mFilePath; |
|
|
int last_slash = directory.ReverseFind(_T('\\')); |
|
|
directory.GetBuffer(0); |
|
|
directory.ReleaseBuffer(last_slash); // Truncate |
|
|
ShellExecute(NULL, _T("open"), directory, _T(""), directory, SW_SHOW); |
|
|
Close(); |
|
|
} |
|
|
|
|
|
void CProgressDialog::OnPause() |
|
|
{ |
|
|
if (!mRequest) return; |
|
|
CString label; |
|
|
if (mPaused) { |
|
|
mRequest->Resume(); |
|
|
label.LoadString(IDS_PAUSE); |
|
|
SetDlgItemText(IDC_PAUSE, label); |
|
|
mPaused = FALSE; |
|
|
} |
|
|
else { |
|
|
mRequest->Suspend(); |
|
|
label.LoadString(IDS_RESUME); |
|
|
SetDlgItemText(IDC_PAUSE, label); |
|
|
mPaused = TRUE; |
|
|
} |
|
|
} |
|
|
|
|
|
void CProgressDialog::OnCancel() { |
|
|
if (mDone){ |
|
|
Close(); |
|
|
} |
|
|
else { |
|
|
Cancel(); |
|
|
Close(); |
|
|
} |
|
|
} |
|
|
|
|
|
void CProgressDialog::OnClose() { |
|
|
if (mDone){ |
|
|
Close(); |
|
|
} |
|
|
else { |
|
|
Cancel(); |
|
|
} |
|
|
} |
|
|
|
|
|
void CProgressDialog::OnOpen() { |
|
|
CString directory = mFilePath; |
|
|
int last_slash = directory.ReverseFind(_T('\\')); |
|
|
directory.GetBuffer(0); |
|
|
directory.ReleaseBuffer(last_slash); // Truncate |
|
|
ShellExecute(NULL, _T("open"), mFilePath, _T(""), directory, SW_SHOW); |
|
|
Close(); |
|
|
} |
|
|
|
|
|
void CProgressDialog::OnBnClickedCloseWhenDone() |
|
|
{ |
|
|
if (IsDlgButtonChecked(IDC_CLOSE_WHEN_DONE)) |
|
|
theApp.preferences.bCloseDownloadDialog = true; |
|
|
else |
|
|
theApp.preferences.bCloseDownloadDialog = false; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CProgressDialog::SetSha256Hash(const nsACString & aHash) |
|
|
{ |
|
|
return NS_ERROR_NOT_IMPLEMENTED; |
|
|
} |
|
|
|
|
|
void CProgressDialog::InitControl(const char *uri, const TCHAR *filepath) |
|
|
{ |
|
|
|
|
|
const TCHAR *file = _tcsrchr(filepath, '\\')+1; |
|
|
mFileName = file; |
|
|
mFilePath = filepath; |
|
|
mUri = strdup(uri); |
|
|
|
|
|
mLastUpdateTime = 0; |
|
|
mTotalBytes = 0; |
|
|
|
|
|
if (m_bWindow) { |
|
|
//To avoid behind released by HelperAppLauncher when the |
|
|
//download is finished. |
|
|
NS_ADDREF_THIS(); |
|
|
|
|
|
Create(IDD_PROGRESS, GetDesktopWindow()); |
|
|
CheckDlgButton(IDC_CLOSE_WHEN_DONE, m_bClose); |
|
|
theApp.RegisterWindow(this); |
|
|
USES_CONVERSION; |
|
|
SetDlgItemText(IDC_SOURCE, A2CT(uri)); |
|
|
SetDlgItemText(IDC_DESTINATION, filepath); |
|
|
if (theApp.preferences.bShowMinimized) |
|
|
ShowWindow(SW_MINIMIZE); |
|
|
else |
|
|
ShowWindow(SW_SHOW); |
|
|
SetIcon(theApp.GetDefaultIcon(FALSE), FALSE); |
|
|
SetIcon(theApp.GetDefaultIcon(TRUE), TRUE); |
|
|
} |
|
|
} |
|
|
|
|
|
void CProgressDialog::SetCallBack(ProgressDialogCallback aCallback, void* aParam) |
|
|
{ |
|
|
mCallback = aCallback; |
|
|
mParam = aParam; |
|
|
} |
|
|
|
|
|
void CProgressDialog::InitPersist(nsIURI *aSource, nsIFile *aTarget, nsIWebBrowserPersist *aPersist, BOOL bShowDialog) |
|
|
{ |
|
|
mCancelable = aPersist; |
|
|
aPersist->SetProgressListener(this); |
|
|
m_bWindow = bShowDialog; |
|
|
|
|
|
nsCString uri; |
|
|
aSource->GetSpec(uri); |
|
|
|
|
|
#ifdef _UNICODE |
|
|
nsString filepath; |
|
|
((nsIFile*)aTarget)->GetPath(filepath); |
|
|
#else |
|
|
nsCString filepath; |
|
|
aTarget->GetNativePath(filepath); |
|
|
#endif |
|
|
|
|
|
mStartTime = PRNow(); |
|
|
|
|
|
InitControl(uri.get(), filepath.get()); |
|
|
} |
|
|
NS_IMETHODIMP CProgressDialog::Init(nsIURI *aSource, nsIURI *aTarget, const nsAString & aDisplayName, nsIMIMEInfo *aMIMEInfo, PRTime startTime, nsIFile *aTempFile, nsICancelable *aCancelable, bool aIsPrivate) |
|
|
//NS_IMETHODIMP CProgressDialog::Init(nsIURI *aSource, nsIURI *aTarget, const nsAString & aDisplayName, nsIMIMEInfo *aMIMEInfo, PRTime startTime, nsILocalFile *aTempFile, nsICancelable *aCancelable) |
|
|
//NS_IMETHODIMP CProgressDialog::Init(nsIURI *aSource, nsIURI *aTarget, const nsAString & aDisplayName, nsIMIMEInfo *aMIMEInfo, PRTime startTime, nsICancelable *aCancelable) |
|
|
{ |
|
|
nsCString uri; |
|
|
#ifdef _UNICODE |
|
|
nsString filepath; |
|
|
nsString tempfile; |
|
|
#else |
|
|
nsCString filepath; |
|
|
nsCString tempfile; |
|
|
#endif |
|
|
|
|
|
aSource->GetSpec(uri); |
|
|
|
|
|
nsCOMPtr<nsIFileURL> tFileUrl = do_QueryInterface(aTarget); |
|
|
if (tFileUrl) |
|
|
{ |
|
|
nsCOMPtr<nsIFile> tFileRef; |
|
|
nsCOMPtr<nsIFile> tTempRef; |
|
|
tFileUrl->GetFile(getter_AddRefs(tFileRef)); |
|
|
//tTempRef->GetFile(getter_AddRefs(aTempFile)); |
|
|
#ifdef _UNICODE |
|
|
tFileRef->GetPath(filepath); |
|
|
aTempFile->GetPath(tempfile); |
|
|
#else |
|
|
tFileRef->GetNativePath(filepath); |
|
|
aTempFile->GetNativePath(tempfile); |
|
|
#endif |
|
|
} |
|
|
|
|
|
if (aMIMEInfo) |
|
|
{ |
|
|
nsHandlerInfoAction action; |
|
|
if (NS_SUCCEEDED(aMIMEInfo->GetPreferredAction(&action))) |
|
|
{ |
|
|
if (action == nsIMIMEInfo::useHelperApp || action == nsIMIMEInfo::useSystemDefault ) |
|
|
m_HandleContentOp = 1; |
|
|
} |
|
|
} |
|
|
|
|
|
mStartTime = startTime; |
|
|
mCancelable = aCancelable; |
|
|
m_bWindow = TRUE; |
|
|
mMIMEInfo = aMIMEInfo; |
|
|
mTarget = aTarget; |
|
|
mTempFile = aTempFile; |
|
|
|
|
|
InitControl(uri.get(), filepath.get()); |
|
|
/* |
|
|
|
|
|
SetDlgItemText(IDC_SOURCE, uri.get()); |
|
|
SetDlgItemText(IDC_DESTINATION, filepath.get()); |
|
|
|
|
|
char *file = strrchr(filepath.get(), '\\')+1; |
|
|
mFileName = strdup(file); |
|
|
mFilePath = strdup(filepath.get()); |
|
|
|
|
|
|
|
|
mLastUpdateTime = 0; |
|
|
*/ |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CProgressDialog::OnRefreshAttempted(nsIWebProgress *aWebProgress, nsIURI *aRefreshURI, int32_t aMillis, bool aSameURI, bool *_retval) |
|
|
{ |
|
|
return NS_ERROR_NOT_IMPLEMENTED; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CProgressDialog::SetRedirects(class nsIArray *) |
|
|
{ |
|
|
return NS_ERROR_NOT_IMPLEMENTED; |
|
|
} |
|
|
|
|
|
void CProgressDialog::OnOK() |
|
|
{ |
|
|
// Prevent the window to close when hitting return |
|
|
//__super::OnOK(); |
|
|
} |
|
|
|
|
|
//***************************************************************************** |
|
|
// CUnknownContentHandlerFactory |
|
|
//***************************************************************************** |
|
|
/* |
|
|
class CDownloadFactory : public nsIFactory |
|
|
{ |
|
|
public: |
|
|
NS_DECL_ISUPPORTS |
|
|
NS_DECL_NSIFACTORY |
|
|
|
|
|
CDownloadFactory(); |
|
|
virtual ~CDownloadFactory(); |
|
|
}; |
|
|
|
|
|
|
|
|
//***************************************************************************** |
|
|
|
|
|
NS_IMPL_ISUPPORTS1(CDownloadFactory, nsIFactory) |
|
|
|
|
|
CDownloadFactory::CDownloadFactory() |
|
|
{ |
|
|
} |
|
|
|
|
|
CDownloadFactory::~CDownloadFactory() |
|
|
{ |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CDownloadFactory::CreateInstance(nsISupports *aOuter, const nsIID & aIID, void **aResult) |
|
|
{ |
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aResult); |
|
|
|
|
|
*aResult = NULL; |
|
|
CProgressDialog *inst = new CProgressDialog; |
|
|
if (!inst) |
|
|
return NS_ERROR_OUT_OF_MEMORY; |
|
|
|
|
|
nsresult rv = inst->QueryInterface(aIID, aResult); |
|
|
if (rv != NS_OK) { |
|
|
// We didn't get the right interface, so clean up |
|
|
delete inst; |
|
|
} |
|
|
|
|
|
return rv; |
|
|
} |
|
|
|
|
|
NS_IMETHODIMP CDownloadFactory::LockFactory(PRBool lock) |
|
|
{ |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
|
|
|
nsresult NewDownloadFactory(nsIFactory** aFactory) { |
|
|
NS_ENSURE_ARG_POINTER(aFactory); |
|
|
*aFactory = nullptr; |
|
|
CDownloadFactory *result = new CDownloadFactory; |
|
|
if (!result) |
|
|
return NS_ERROR_OUT_OF_MEMORY; |
|
|
NS_ADDREF(result); |
|
|
*aFactory = result; |
|
|
return NS_OK; |
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
// Bo<EFBFBD><EFBFBD>e de dialogue COpenSaveDlg |
|
|
|
|
|
//IMPLEMENT_DYNAMIC(COpenSaveDlg, CDialog) |
|
|
COpenSaveDlg::COpenSaveDlg(CWnd* pParent /*=NULL*/) |
|
|
: CDialog(COpenSaveDlg::IDD, pParent) |
|
|
, m_csFilename(_T("")) |
|
|
, m_csFiletype(_T("")) |
|
|
, m_csSource(_T("")) |
|
|
{ |
|
|
} |
|
|
|
|
|
COpenSaveDlg::~COpenSaveDlg() |
|
|
{ |
|
|
} |
|
|
|
|
|
void COpenSaveDlg::DoDataExchange(CDataExchange* pDX) |
|
|
{ |
|
|
CDialog::DoDataExchange(pDX); |
|
|
DDX_Text(pDX, IDC_DOWNLOAD_NAME, m_csFilename); |
|
|
DDX_Text(pDX, IDC_DOWNLOAD_TYPE, m_csFiletype); |
|
|
DDX_Text(pDX, IDC_DOWNLOAD_SOURCE, m_csSource); |
|
|
DDX_Control(pDX, IDC_FILE_ICON, m_cFileIcon); |
|
|
} |
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(COpenSaveDlg, CDialog) |
|
|
ON_BN_CLICKED(IDOPEN, OnBnClickedOpen) |
|
|
ON_WM_TIMER() |
|
|
ON_WM_DESTROY() |
|
|
END_MESSAGE_MAP() |
|
|
|
|
|
void COpenSaveDlg::OnBnClickedOpen() |
|
|
{ |
|
|
EndDialog(IDOPEN); |
|
|
} |
|
|
|
|
|
// Use the same routine than mozilla to avoid trouble |
|
|
BOOL IsExecutable(const TCHAR* filename) |
|
|
{ |
|
|
// Get extension. |
|
|
TCHAR * _ext = (TCHAR *) _tcsrchr(filename, _T('.')); |
|
|
USES_CONVERSION; |
|
|
char* ext = T2A(_ext); |
|
|
if ( ext ) { |
|
|
// Convert extension to lower case. |
|
|
for( char *p = ext; *p; p++ ) |
|
|
*p = tolower(*p); |
|
|
|
|
|
// Search for any of the set of executable extensions. |
|
|
const char * const executableExts[] = { |
|
|
".ad", |
|
|
".adp", |
|
|
".asp", |
|
|
".bas", |
|
|
".bat", |
|
|
".chm", |
|
|
".cmd", |
|
|
".com", |
|
|
".cpl", |
|
|
".crt", |
|
|
".exe", |
|
|
".hlp", |
|
|
".hta", |
|
|
".inf", |
|
|
".ins", |
|
|
".isp", |
|
|
".js", |
|
|
".jse", |
|
|
".lnk", |
|
|
".mdb", |
|
|
".mde", |
|
|
".msc", |
|
|
".msi", |
|
|
".msp", |
|
|
".mst", |
|
|
".pcd", |
|
|
".pif", |
|
|
".reg", |
|
|
".scr", |
|
|
".sct", |
|
|
".shb", |
|
|
".shs", |
|
|
".url", |
|
|
".vb", |
|
|
".vbe", |
|
|
".vbs", |
|
|
".vsd", |
|
|
".vss", |
|
|
".vst", |
|
|
".vsw", |
|
|
".ws", |
|
|
".wsc", |
|
|
".wsf", |
|
|
".wsh", |
|
|
0 }; |
|
|
for ( int i = 0; executableExts[i]; i++ ) { |
|
|
if ( strcmp( executableExts[i], ext ) == 0 ) { |
|
|
return TRUE; |
|
|
} |
|
|
} |
|
|
} |
|
|
return FALSE; |
|
|
} |
|
|
|
|
|
BOOL COpenSaveDlg::OnInitDialog() |
|
|
{ |
|
|
CDialog::OnInitDialog(); |
|
|
|
|
|
// If we have an application disable the open button |
|
|
if (IsExecutable(m_csFilename)) |
|
|
{ |
|
|
CWnd* openButton = GetDlgItem(IDOPEN); |
|
|
openButton->EnableWindow(FALSE); |
|
|
//SetTimer(2, 2000, NULL); |
|
|
} |
|
|
|
|
|
// Set the icon |
|
|
SHFILEINFO shfi; |
|
|
if (SHGetFileInfo(m_csFilename, 0, &shfi, sizeof(SHFILEINFO),SHGFI_USEFILEATTRIBUTES|SHGFI_ICON|SHGFI_SHELLICONSIZE)) |
|
|
m_cFileIcon.SetIcon(shfi.hIcon); |
|
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control |
|
|
} |
|
|
|
|
|
void COpenSaveDlg::OnTimer(UINT nIDEvent) |
|
|
{ |
|
|
if (nIDEvent == 2) |
|
|
{ |
|
|
KillTimer(nIDEvent); |
|
|
CWnd* openButton = GetDlgItem(IDOPEN); |
|
|
openButton->EnableWindow(); |
|
|
} |
|
|
|
|
|
CDialog::OnTimer(nIDEvent); |
|
|
} |
|
|
|
|
|
void COpenSaveDlg::OnDestroy() |
|
|
{ |
|
|
CDialog::OnDestroy(); |
|
|
DestroyIcon(m_cFileIcon.GetIcon()); |
|
|
} |
|
|
|
|
|
BOOL CProgressDialog::OnQueryEndSession() |
|
|
{ |
|
|
if (!__super::OnQueryEndSession()) |
|
|
return FALSE; |
|
|
|
|
|
if (m_bWindow) |
|
|
return FALSE; |
|
|
|
|
|
return TRUE; |
|
|
}
|
|
|
|