Bug 285517 show better message in helper app dialog when the type was sniffed from text/plain

r=bz sr=darin


git-svn-id: svn://10.0.0.236/trunk@170609 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
cbiesinger%web.de 2005-03-13 17:03:44 +00:00
parent f090b71376
commit 8593d723e5
13 changed files with 136 additions and 143 deletions

View File

@ -222,9 +222,9 @@ CHBrowserService::CreateChromeWindow(nsIWebBrowserChrome *parent,
}
// void show( in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in boolean aForced );
// void show( in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in unsigned long aReason );
NS_IMETHODIMP
CHBrowserService::Show(nsIHelperAppLauncher* inLauncher, nsISupports* inContext, PRBool aForced)
CHBrowserService::Show(nsIHelperAppLauncher* inLauncher, nsISupports* inContext, PRUint32 aReason)
{
PRBool autoDownload = PR_FALSE;

View File

@ -436,9 +436,9 @@ CHelperAppLauncherDlg::~CHelperAppLauncherDlg()
{
}
/* void show (in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in boolean aForced); */
/* void show (in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in unsigned long aReason); */
NS_IMETHODIMP
CHelperAppLauncherDlg::Show(nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRBool aForced)
CHelperAppLauncherDlg::Show(nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRUint32 aReason)
{
NS_ENSURE_ARG_POINTER(aLauncher);

View File

@ -225,9 +225,9 @@ CHBrowserService::CreateChromeWindow(nsIWebBrowserChrome *parent,
}
// void show( in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in boolean aForced );
// void show( in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in unsigned long aReason );
NS_IMETHODIMP
CHBrowserService::Show(nsIHelperAppLauncher* inLauncher, nsISupports* inContext, PRBool aForced)
CHBrowserService::Show(nsIHelperAppLauncher* inLauncher, nsISupports* inContext, PRUint32 aReason)
{
// Old way - always prompt to save file to disk
return inLauncher->SaveToDisk(nsnull, PR_FALSE);

View File

@ -60,7 +60,7 @@ nsUnknownContentTypeHandler::~nsUnknownContentTypeHandler( )
}
NS_IMETHODIMP nsUnknownContentTypeHandler::Show( nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRBool aForced )
NS_IMETHODIMP nsUnknownContentTypeHandler::Show( nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRUint32 aReason )
{
return aLauncher->SaveToDisk( nsnull, PR_FALSE );
}

View File

@ -280,8 +280,8 @@ CHelperAppLauncherDialog::~CHelperAppLauncherDialog()
NS_IMPL_ISUPPORTS1(CHelperAppLauncherDialog, nsIHelperAppLauncherDialog)
/* void show (in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in boolean aForced); */
NS_IMETHODIMP CHelperAppLauncherDialog::Show(nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRBool aForced)
/* void show (in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in unsigned long aReason); */
NS_IMETHODIMP CHelperAppLauncherDialog::Show(nsIHelperAppLauncher *aLauncher, nsISupports *aContext, PRUint32 aReason)
{
return aLauncher->SaveToDisk(nsnull, PR_FALSE);
}

View File

@ -48,6 +48,11 @@
* nsHelperAppDialog component.
*/
const nsIHelperAppLauncherDialog = Components.interfaces.nsIHelperAppLauncherDialog;
const REASON_CANTHANDLE = nsIHelperAppLauncherDialog.REASON_CANTHANDLE;
const REASON_SERVERREQUEST = nsIHelperAppLauncherDialog.REASON_SERVERREQUEST;
const REASON_TYPESNIFFED = nsIHelperAppLauncherDialog.REASON_TYPESNIFFED;
/* ctor
*/
@ -93,10 +98,10 @@ nsHelperAppDialog.prototype = {
// show: Open XUL dialog using window watcher. Since the dialog is not
// modal, it needs to be a top level window and the way to open
// one of those is via that route).
show: function(aLauncher, aContext, aForced) {
show: function(aLauncher, aContext, aReason) {
this.mLauncher = aLauncher;
this.mContext = aContext;
this.mForced = aForced;
this.mReason = aReason;
// Display the dialog using the Window Watcher interface.
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService( Components.interfaces.nsIWindowWatcher );
@ -281,9 +286,10 @@ nsHelperAppDialog.prototype = {
// Initialize "always ask me" box. This should always be disabled
// and set to true for the ambiguous type application/octet-stream.
// Same if this dialog was forced
// Same if this dialog was forced due to a server request or type
// sniffing
var alwaysHandleCheckbox = this.dialogElement( "alwaysHandle" );
if (this.mForced ||
if (this.mReason != REASON_CANTHANDLE ||
this.mLauncher.MIMEInfo.MIMEType == "application/octet-stream"){
alwaysHandleCheckbox.checked = false;
alwaysHandleCheckbox.disabled = true;
@ -314,25 +320,20 @@ nsHelperAppDialog.prototype = {
initIntro: function(url, filename) {
var intro = this.dialogElement( "intro" );
var desc = this.mLauncher.MIMEInfo.description;
var text;
if ( this.mReason == REASON_CANTHANDLE )
text = "intro.";
else if (this.mReason == REASON_SERVERREQUEST )
text = "intro.attachment.";
else if (this.mReason == REASON_TYPESNIFFED )
text = "intro.sniffed.";
var modified;
if ( this.mForced && desc )
{
modified = this.replaceInsert( this.getString( "intro.attachment.label" ), 1, desc );
}
else if ( this.mForced && !desc )
{
modified = this.getString( "intro.attachment.noDesc.label" );
}
else if ( desc )
{
// Use intro with descriptive text.
modified = this.replaceInsert( this.getString( "intro.withDesc" ), 1, desc );
}
if (desc)
modified = this.replaceInsert( this.getString( text + "label" ), 1, desc );
else
{
// Use intro without descriptive text.
modified = this.getString( "intro.noDesc" );
}
modified = this.getString( text + "noDesc.label" );
modified = this.replaceInsert( modified, 2, this.mLauncher.MIMEInfo.MIMEType );
modified = this.replaceInsert( modified, 3, filename);
@ -454,10 +455,12 @@ nsHelperAppDialog.prototype = {
}
var useDefault = this.dialogElement( "useSystemDefault" );;
if (this.mLauncher.MIMEInfo.preferredAction == this.nsIMIMEInfo.useSystemDefault && !this.mForced) {
if (this.mLauncher.MIMEInfo.preferredAction == this.nsIMIMEInfo.useSystemDefault &&
this.mReason != REASON_SERVERREQUEST) {
// Open (using system default).
useDefault.radioGroup.selectedItem = useDefault;
} else if (this.mLauncher.MIMEInfo.preferredAction == this.nsIMIMEInfo.useHelperApp && !this.mForced) {
} else if (this.mLauncher.MIMEInfo.preferredAction == this.nsIMIMEInfo.useHelperApp &&
this.mReason != REASON_SERVERREQUEST) {
// Open with given helper app.
var openUsing = this.dialogElement( "openUsing" );
openUsing.radioGroup.selectedItem = openUsing;
@ -556,8 +559,9 @@ nsHelperAppDialog.prototype = {
// If current selection differs from what's in the mime info object,
// then we need to update.
// However, we don't want to change the action all nsIMIMEInfo objects to
// saveToDisk if mForced is true.
if ( this.dialogElement( "saveToDisk" ).selected && !this.mForced ) {
// saveToDisk if mReason is REASON_SERVERREQUEST.
if ( this.dialogElement( "saveToDisk" ).selected &&
this.mReason != REASON_SERVERREQUEST ) {
needUpdate = this.mLauncher.MIMEInfo.preferredAction != this.nsIMIMEInfo.saveToDisk;
if ( needUpdate )
this.mLauncher.MIMEInfo.preferredAction = this.nsIMIMEInfo.saveToDisk;
@ -578,7 +582,7 @@ nsHelperAppDialog.prototype = {
}
}
// Only care about the state of "always ask" if this dialog wasn't forced
if ( !this.mForced )
if ( this.mReason == REASON_CANTHANDLE )
{
// We will also need to update if the "always ask" flag has changed.
needUpdate = needUpdate || this.mLauncher.MIMEInfo.alwaysAskBeforeHandling == this.dialogElement( "alwaysHandle" ).checked;

View File

@ -109,10 +109,12 @@
<!-- Localizable strings (from .dtd) -->
<strings style="display:none;">
<string id="brandShortName"> &brandShortName; </string>
<string id="intro.withDesc"> &intro.label; </string>
<string id="intro.noDesc"> &intro.noDesc.label; </string>
<string id="intro.label"> &intro.label; </string>
<string id="intro.noDesc.label"> &intro.noDesc.label; </string>
<string id="intro.attachment.label"> &intro.attachment.label; </string>
<string id="intro.attachment.noDesc.label">&intro.attachment.noDesc.label;</string>
<string id="intro.sniffed.label"> &intro.sniffed.label; </string>
<string id="intro.sniffed.noDesc.label"> &intro.sniffed.noDesc.label; </string>
<string id="defaultApp"> &useSystemDefault.label; </string>
<string id="badApp"> &badApp; </string>
<string id="badApp.title"> &badApp.title; </string>

View File

@ -210,7 +210,7 @@ CWnd* CHelperAppLauncherDialog::GetParentFromContext(nsISupports *aWindowContext
//
NS_IMETHODIMP CHelperAppLauncherDialog::Show(nsIHelperAppLauncher *aLauncher,
nsISupports *aContext,
PRBool aForced)
PRUint32 aReason)
{
ResourceState setState;

View File

@ -15,6 +15,9 @@
<!ENTITY intro.attachment.label "The site has suggested that &quot;#3&quot; be handled as an attachment. It is of type #2 (#1) and located at:">
<!ENTITY intro.attachment.noDesc.label "The site has suggested that &quot;#3&quot; be handled as an attachment. It is of type #2 and located at:">
<!ENTITY intro.sniffed.label "#4 has detected that the file &quot;#3&quot; is likely to be of type #2 (#1). The file is located at:">
<!ENTITY intro.sniffed.noDesc.label "#4 has detected that the file &quot;#3&quot; is likely to be of type #2. The file is located at:">
<!ENTITY prompt.label "What should #1 do with this file?">
<!ENTITY alwaysHandle.label "Always perform this action when handling files of this type">

View File

@ -82,7 +82,7 @@ nsUnknownContentTypeDialog.prototype = {
// show: Open XUL dialog using window watcher. Since the dialog is not
// modal, it needs to be a top level window and the way to open
// one of those is via that route).
show: function(aLauncher, aContext) {
show: function(aLauncher, aContext, aReason) {
this.mLauncher = aLauncher;
this.mContext = aContext;
// Display the dialog using the Window Watcher interface.

View File

@ -565,7 +565,7 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const nsACString& aMimeConte
{
nsAutoString fileName;
nsCAutoString fileExtension;
PRBool isAttachment = PR_FALSE;
PRUint32 reason = nsIHelperAppLauncherDialog::REASON_CANTHANDLE;
nsresult rv;
// Get the file extension and name that we will need later
@ -612,12 +612,14 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const nsACString& aMimeConte
}
}
// Extract name & extension
isAttachment = GetFilenameAndExtensionFromChannel(channel, fileName,
fileExtension,
allowURLExt);
PRBool isAttachment = GetFilenameAndExtensionFromChannel(channel, fileName,
fileExtension,
allowURLExt);
LOG(("Found extension '%s' (filename is '%s', handling attachment: %i)",
fileExtension.get(), NS_ConvertUTF16toUTF8(fileName).get(),
isAttachment));
if (isAttachment)
reason = nsIHelperAppLauncherDialog::REASON_SERVERREQUEST;
}
LOG(("HelperAppService::DoContent: mime '%s', extension '%s'\n",
@ -645,6 +647,9 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const nsACString& aMimeConte
}
if (channel)
channel->SetContentType(mimeType);
// Don't overwrite SERVERREQUEST
if (reason == nsIHelperAppLauncherDialog::REASON_CANTHANDLE)
reason = nsIHelperAppLauncherDialog::REASON_TYPESNIFFED;
}
else {
GetFromTypeAndExtension(aMimeContentType, fileExtension,
@ -658,16 +663,15 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const nsACString& aMimeConte
*aStreamListener = nsnull;
// We want the mimeInfo's primary extension to pass it to
// CreateNewExternalHandler
// nsExternalAppHandler
nsCAutoString buf;
mimeInfo->GetPrimaryExtension(buf);
// this code is incomplete and just here to get things started..
nsExternalAppHandler * handler = CreateNewExternalHandler(mimeInfo,
nsExternalAppHandler * handler = new nsExternalAppHandler(mimeInfo,
buf,
aWindowContext,
fileName,
isAttachment,
aWindowContext);
reason);
if (!handler)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aStreamListener = handler);
@ -691,23 +695,6 @@ NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension(const nsACSt
return NS_OK;
}
nsExternalAppHandler * nsExternalHelperAppService::CreateNewExternalHandler(nsIMIMEInfo * aMIMEInfo,
const nsCSubstring& aTempFileExtension,
const nsAString& aFileName,
PRBool aIsAttachment,
nsIInterfaceRequestor * aWindowContext)
{
nsExternalAppHandler* handler = nsnull;
NS_NEWXPCOM(handler, nsExternalAppHandler);
if (!handler)
return nsnull;
// add any XP intialization code for an external handler that we may need here...
// right now we don't have any but i bet we will before we are done.
handler->Init(aMIMEInfo, aTempFileExtension, aWindowContext, aFileName, aIsAttachment);
return handler;
}
nsresult nsExternalHelperAppService::FillTopLevelProperties(nsIRDFResource * aContentTypeNodeResource,
nsIRDFService * aRDFService, nsIMIMEInfo * aMIMEInfo)
{
@ -1361,16 +1348,35 @@ NS_INTERFACE_MAP_BEGIN(nsExternalAppHandler)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_END_THREADSAFE
nsExternalAppHandler::nsExternalAppHandler()
nsExternalAppHandler::nsExternalAppHandler(nsIMIMEInfo * aMIMEInfo,
const nsCSubstring& aTempFileExtension,
nsIInterfaceRequestor* aWindowContext,
const nsAString& aSuggestedFilename,
PRUint32 aReason)
: mMimeInfo(aMIMEInfo)
, mWindowContext(aWindowContext)
, mSuggestedFileName(aSuggestedFilename)
, mCanceled(PR_FALSE)
, mReceivedDispositionInfo(PR_FALSE)
, mStopRequestIssued(PR_FALSE)
, mProgressListenerInitialized(PR_FALSE)
, mReason(aReason)
, mProgress(0)
, mContentLength(-1)
, mRequest(nsnull)
{
mCanceled = PR_FALSE;
mReceivedDispositionInfo = PR_FALSE;
mHandlingAttachment = PR_FALSE;
mStopRequestIssued = PR_FALSE;
mProgressListenerInitialized = PR_FALSE;
mContentLength = -1;
mProgress = 0;
mRequest = nsnull;
// make sure the extention includes the '.'
if (!aTempFileExtension.IsEmpty() && aTempFileExtension.First() != '.')
mTempFileExtension = PRUnichar('.');
AppendUTF8toUTF16(aTempFileExtension, mTempFileExtension);
// replace platform specific path separator and illegal characters to avoid any confusion
mSuggestedFileName.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '-');
mTempFileExtension.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '-');
// Make sure extension is correct.
EnsureSuggestedFileName();
sSrv->AddRef();
}
@ -1677,7 +1683,7 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest *request, nsISuppo
PRBool alwaysAsk = PR_TRUE;
// If we're handling an attachment we want to default to saving but
// always ask just in case
if (!mHandlingAttachment)
if (mReason == nsIHelperAppLauncherDialog::REASON_CANTHANDLE)
{
mMimeInfo->GetAlwaysAskBeforeHandling(&alwaysAsk);
}
@ -1719,7 +1725,7 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest *request, nsISuppo
// this will create a reference cycle (the dialog holds a reference to us as
// nsIHelperAppLauncher), which will be broken in Cancel or
// CreateProgressListener.
rv = mDialog->Show( this, mWindowContext, mHandlingAttachment );
rv = mDialog->Show( this, mWindowContext, mReason );
// what do we do if the dialog failed? I guess we should call Cancel and abort the load....
}
@ -2052,33 +2058,6 @@ nsresult nsExternalAppHandler::ExecuteDesiredAction()
return rv;
}
nsresult nsExternalAppHandler::Init(nsIMIMEInfo * aMIMEInfo,
const nsCSubstring& aTempFileExtension,
nsIInterfaceRequestor* aWindowContext,
const nsAString& aSuggestedFilename,
PRBool aIsAttachment)
{
mWindowContext = aWindowContext;
mMimeInfo = aMIMEInfo;
mHandlingAttachment = aIsAttachment;
// make sure the extention includes the '.'
if (!aTempFileExtension.IsEmpty() && aTempFileExtension.First() != '.')
mTempFileExtension = PRUnichar('.');
AppendUTF8toUTF16(aTempFileExtension, mTempFileExtension);
mSuggestedFileName = aSuggestedFilename;
// replace platform specific path separator and illegal characters to avoid any confusion
mSuggestedFileName.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '-');
mTempFileExtension.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '-');
// Make sure extension is correct.
EnsureSuggestedFileName();
return NS_OK;
}
NS_IMETHODIMP nsExternalAppHandler::GetMIMEInfo(nsIMIMEInfo ** aMIMEInfo)
{
*aMIMEInfo = mMimeInfo;

View File

@ -113,26 +113,6 @@ public:
* this service is first instantiated.
*/
NS_HIDDEN_(nsresult) Init();
/**
* Create an external app handler and binds it with a mime info object which
* represents how we want to dispose of this content.
* CreateNewExternalHandler is implemented only by the base class.
* @param aMIMEInfo MIMEInfo object, representing the type of the
* content that should be handled
* @param aFileExtension The extension we need to append to our temp file,
* INCLUDING the ".". e.g. .mp3
* @param aFileName The filename to use
* @param aIsAttachment Whether the request has Content-Disposition: attachment
* set
* @param aWindowContext Window context, as passed to DoContent
*/
NS_HIDDEN_(nsExternalAppHandler *)
CreateNewExternalHandler(nsIMIMEInfo * aMIMEInfo,
const nsCSubstring& aFileExtension,
const nsAString& aFileName,
PRBool aIsAttachment,
nsIInterfaceRequestor* aWindowContext);
/**
* Given a content type, look up the user override information to see if
@ -349,13 +329,22 @@ public:
NS_DECL_NSIHELPERAPPLAUNCHER
NS_DECL_NSIOBSERVER
nsExternalAppHandler();
~nsExternalAppHandler();
/**
* @param aMIMEInfo MIMEInfo object, representing the type of the
* content that should be handled
* @param aFileExtension The extension we need to append to our temp file,
* INCLUDING the ".". e.g. .mp3
* @param aWindowContext Window context, as passed to DoContent
* @param aFileName The filename to use
* @param aReason A constant from nsIHelperAppLauncherDialog indicating
* why the request is handled by a helper app.
*/
nsExternalAppHandler(nsIMIMEInfo * aMIMEInfo, const nsCSubstring& aFileExtension,
nsIInterfaceRequestor * aWindowContext,
const nsAString& aFilename,
PRUint32 aReason);
nsresult Init(nsIMIMEInfo * aMIMEInfo, const nsCSubstring& aFileExtension,
nsIInterfaceRequestor * aWindowContext,
const nsAString& aFilename,
PRBool aIsAttachment);
~nsExternalAppHandler();
protected:
nsCOMPtr<nsIFile> mTempFile;
@ -387,8 +376,14 @@ protected:
PRPackedBool mReceivedDispositionInfo;
PRPackedBool mStopRequestIssued;
PRPackedBool mProgressListenerInitialized;
/// This is set when handling something with "Content-Disposition: attachment"
PRPackedBool mHandlingAttachment;
/**
* One of the REASON_ constants from nsIHelperAppLauncherDialog. Indicates the
* reason the dialog was shown (unknown content type, server requested it,
* etc).
*/
PRUint32 mReason;
PRTime mTimeDownloadStarted;
PRInt32 mContentLength;
PRInt32 mProgress; /**< Number of bytes received (for sending progress notifications). */

View File

@ -41,8 +41,6 @@ interface nsIHelperAppLauncher;
interface nsILocalFile;
/**
* nsIHelperAppLauncherDialog
* ==========================
* This interface is used to display a confirmatino dialog before
* launching a "helper app" to handle content not handled by
* Mozilla.
@ -54,22 +52,34 @@ interface nsILocalFile;
* The dialog is shown non-modally. The implementation of the dialog
* will access methods of the nsIHelperAppLauncher passed in to show()
* in order to cause a "save to disk" or "open using" action.
*
* Note: The promptForSaveToFile method is
* obsolescent. Caller(s) will be converted to use specific
* file-picker and progress-dialog interfaces.
*/
[scriptable, uuid(d7ebddf0-4c84-11d4-807a-00600811a9c3)]
[scriptable, uuid(64355793-988d-40a5-ba8e-fcde78cac631)]
interface nsIHelperAppLauncherDialog : nsISupports {
/**
* This request is passed to the helper app dialog because Gecko can not
* handle content of this type.
*/
const unsigned long REASON_CANTHANDLE = 0;
/**
* The server requested external handling.
*/
const unsigned long REASON_SERVERREQUEST = 1;
/**
* Gecko detected that the type sent by the server (e.g. text/plain) does
* not match the actual type.
*/
const unsigned long REASON_TYPESNIFFED = 2;
// Show confirmation dialog for launching application (or "save to
// disk") for content specified by aLauncher.
// aForced is used to indicate whether this dialog was shown even though
// the content could have been handled by mozilla; this is used if
// an HTTP Server sends Content-Disposition: attachment
// aReason is one of the constants from above. It indicates why the dialog is
// shown.
// Implementors should treat unknown reasons like REASON_CANTHANDLE.
void show(in nsIHelperAppLauncher aLauncher,
in nsISupports aContext,
in boolean aForced);
in unsigned long aReason);
// invoke a save to file dialog instead of the full fledged helper app dialog.
// aDefaultFileName --> default file name to provide (can be null)