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:
Родитель
d21bdbe4ac
Коммит
bf94a50628
|
@ -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 "#3" be handled as an attachment. It is of type #2 (#1) and located at:">
|
||||
<!ENTITY intro.attachment.noDesc.label "The site has suggested that "#3" be handled as an attachment. It is of type #2 and located at:">
|
||||
|
||||
<!ENTITY intro.sniffed.label "#4 has detected that the file "#3" is likely to be of type #2 (#1). The file is located at:">
|
||||
<!ENTITY intro.sniffed.noDesc.label "#4 has detected that the file "#3" 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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче