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

r=bz sr=darin
This commit is contained in:
cbiesinger%web.de 2005-03-13 17:03:44 +00:00
Родитель d21bdbe4ac
Коммит bf94a50628
13 изменённых файлов: 134 добавлений и 432 удалений

Просмотреть файл

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

Просмотреть файл

@ -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);

Просмотреть файл

@ -1,291 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "CHBrowserService.h"
#import "CHDownloadFactories.h"
#import "CHBrowserView.h"
#include "nsIWindowWatcher.h"
#include "nsIWebBrowserChrome.h"
#include "nsCRT.h"
#include "nsString.h"
#include "nsIGenericFactory.h"
#include "nsIComponentRegistrar.h"
#include "nsEmbedAPI.h"
#include "nsIDownload.h"
#include "nsIExternalHelperAppService.h"
NSString* TermEmbeddingNotificationName = @"TermEmbedding";
NSString* XPCOMShutDownNotificationName = @"XPCOMShutDown";
nsAlertController* CHBrowserService::sController = nsnull;
CHBrowserService* CHBrowserService::sSingleton = nsnull;
PRUint32 CHBrowserService::sNumBrowsers = 0;
PRBool CHBrowserService::sCanTerminate = PR_FALSE;
// CHBrowserService implementation
CHBrowserService::CHBrowserService()
{
}
CHBrowserService::~CHBrowserService()
{
}
NS_IMPL_ISUPPORTS3(CHBrowserService,
nsIWindowCreator,
nsIFactory,
nsIHelperAppLauncherDialog)
/* static */
nsresult
CHBrowserService::InitEmbedding()
{
sNumBrowsers++;
if (sSingleton)
return NS_OK;
sSingleton = new CHBrowserService();
if (!sSingleton)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(sSingleton);
// Register as the window creator
nsCOMPtr<nsIWindowWatcher> watcher(do_GetService("@mozilla.org/embedcomp/window-watcher;1"));
if (!watcher)
return NS_ERROR_FAILURE;
watcher->SetWindowCreator(sSingleton);
nsCOMPtr<nsIComponentRegistrar> cr;
NS_GetComponentRegistrar(getter_AddRefs(cr));
if ( !cr )
return NS_ERROR_FAILURE;
// replace the external helper app dialog with our own
#define NS_HELPERAPPLAUNCHERDIALOG_CID \
{0xf68578eb, 0x6ec2, 0x4169, {0xae, 0x19, 0x8c, 0x62, 0x43, 0xf0, 0xab, 0xe1}}
static NS_DEFINE_CID(kHelperDlgCID, NS_HELPERAPPLAUNCHERDIALOG_CID);
nsresult rv = cr->RegisterFactory(kHelperDlgCID, NS_IHELPERAPPLAUNCHERDLG_CLASSNAME, NS_IHELPERAPPLAUNCHERDLG_CONTRACTID,
sSingleton);
// replace the downloader with our own which does not rely on the xpfe downlaod manager
nsCOMPtr<nsIFactory> downloadFactory;
rv = NewDownloadListenerFactory(getter_AddRefs(downloadFactory));
if (NS_FAILED(rv)) return rv;
static NS_DEFINE_CID(kDownloadCID, NS_DOWNLOAD_CID);
rv = cr->RegisterFactory(kDownloadCID, "Download", NS_TRANSFER_CONTRACTID, downloadFactory);
return rv;
}
/* static */
void
CHBrowserService::BrowserClosed()
{
sNumBrowsers--;
if (sCanTerminate && sNumBrowsers == 0) {
// The app is terminating *and* our count dropped to 0.
ShutDown();
}
}
/* static */
void
CHBrowserService::TermEmbedding()
{
// phase 1 notification (we're trying to terminate)
[[NSNotificationCenter defaultCenter] postNotificationName:TermEmbeddingNotificationName object:nil];
sCanTerminate = PR_TRUE;
if (sNumBrowsers == 0) {
ShutDown();
}
else {
#if DEBUG
NSLog(@"Cannot yet shut down embedding.");
#endif
// Otherwise we cannot yet terminate. We have to let the death of the browser views
// induce termination.
}
}
/* static */
void CHBrowserService::ShutDown()
{
// phase 2 notifcation (we really are about to terminate)
[[NSNotificationCenter defaultCenter] postNotificationName:XPCOMShutDownNotificationName object:nil];
NS_IF_RELEASE(sSingleton);
NS_TermEmbedding();
#if DEBUG
NSLog(@"Shutting down embedding.");
#endif
}
#define NS_ALERT_NIB_NAME "alert"
nsAlertController*
CHBrowserService::GetAlertController()
{
if (!sController) {
NSBundle* bundle = [NSBundle bundleForClass:[CHBrowserView class]];
[bundle loadNibFile:@NS_ALERT_NIB_NAME externalNameTable:nsnull withZone:[NSApp zone]];
}
return sController;
}
void
CHBrowserService::SetAlertController(nsAlertController* aController)
{
// XXX When should the controller be released?
sController = aController;
[sController retain];
}
// nsIFactory implementation
NS_IMETHODIMP
CHBrowserService::CreateInstance(nsISupports *aOuter,
const nsIID & aIID,
void **aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
/*
if (aIID.Equals(NS_GET_IID(nsIHelperAppLauncherDialog)))
{
}
*/
return sSingleton->QueryInterface(aIID, aResult);
}
NS_IMETHODIMP
CHBrowserService::LockFactory(PRBool lock)
{
return NS_OK;
}
// Implementation of nsIWindowCreator
/* nsIWebBrowserChrome createChromeWindow (in nsIWebBrowserChrome parent, in PRUint32 chromeFlags); */
NS_IMETHODIMP
CHBrowserService::CreateChromeWindow(nsIWebBrowserChrome *parent,
PRUint32 chromeFlags,
nsIWebBrowserChrome **_retval)
{
if (!parent) {
#if DEBUG
NSLog(@"Attempt to create a new browser window with a null parent. Should not happen in Chimera.");
#endif
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIWindowCreator> browserChrome(do_QueryInterface(parent));
return browserChrome->CreateChromeWindow(parent, chromeFlags, _retval);
}
// void show( in nsIHelperAppLauncher aLauncher, in nsISupports aContext, in boolean aForced );
NS_IMETHODIMP
CHBrowserService::Show(nsIHelperAppLauncher* inLauncher, nsISupports* inContext, PRBool aForced)
{
// Old way - always prompt to save file to disk
return inLauncher->SaveToDisk(nsnull, PR_FALSE);
// New way - just save the file to disk in download folder and invoke the default helper app
// XXX fix me. We need to update the downlaod dialog UI to account for this,
// and warn if the user is launching an executable.
//return inLauncher->LaunchWithApplication(nsnull, PR_FALSE);
}
NS_IMETHODIMP
CHBrowserService::PromptForSaveToFile(nsIHelperAppLauncher* aLauncher,
nsISupports *aWindowContext,
const PRUnichar *aDefaultFile,
const PRUnichar *aSuggestedFileExtension,
nsILocalFile **_retval)
{
NSString* filename = [NSString stringWithPRUnichars:aDefaultFile];
NSSavePanel *thePanel = [NSSavePanel savePanel];
// Note: although the docs for NSSavePanel specifically state "path and filename can be empty strings, but
// cannot be nil" if you want the last used directory to persist between calls to display the save panel
// use nil for the path given to runModalForDirectory
int runResult = [thePanel runModalForDirectory: nil file:filename];
if (runResult == NSOKButton) {
// NSLog(@"Saving to %@", [thePanel filename]);
NSString *theName = [thePanel filename];
return NS_NewNativeLocalFile(nsDependentCString([theName fileSystemRepresentation]), PR_FALSE, _retval);
}
return NS_ERROR_FAILURE;
}
//
// RegisterAppComponents
//
// Register application-provided Gecko components.
//
void
CHBrowserService::RegisterAppComponents(const nsModuleComponentInfo* inComponents, const int inNumComponents)
{
nsCOMPtr<nsIComponentRegistrar> cr;
NS_GetComponentRegistrar(getter_AddRefs(cr));
if ( !cr )
return;
for (int i = 0; i < inNumComponents; ++i) {
nsCOMPtr<nsIGenericFactory> componentFactory;
nsresult rv = NS_NewGenericFactory(getter_AddRefs(componentFactory), &(inComponents[i]));
if (NS_FAILED(rv)) {
NS_ASSERTION(PR_FALSE, "Unable to create factory for component");
continue;
}
rv = cr->RegisterFactory(inComponents[i].mCID,
inComponents[i].mDescription,
inComponents[i].mContractID,
componentFactory);
NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to register factory for component");
}
}

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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>

Просмотреть файл

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

Просмотреть файл

@ -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">

Просмотреть файл

@ -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.

Просмотреть файл

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

Просмотреть файл

@ -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). */

Просмотреть файл

@ -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)