Refactor nsIMIMEInfo and nsExternalHelperAppService to support local and web-based protocol handlers (bug 384374), r=biesi, sr=sicking

This commit is contained in:
dmose@mozilla.org 2007-07-05 12:31:44 -07:00
Родитель 10dbfc6ede
Коммит ec036ba262
19 изменённых файлов: 814 добавлений и 332 удалений

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

@ -54,6 +54,7 @@
#include "nsOSHelperAppService.h"
#include "nsExternalProtocolHandler.h"
#include "nsPrefetchService.h"
#include "nsHandlerAppImpl.h"
// session history
#include "nsSHEntry.h"
@ -99,6 +100,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsOSHelperAppService, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsExternalProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBlockedExternalProtocolHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrefetchService, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsLocalHandlerApp)
#if defined(XP_MAC) || defined(XP_MACOSX)
#include "nsInternetConfigService.h"
@ -203,11 +205,13 @@ static const nsModuleComponentInfo gDocShellModuleInfo[] = {
nsBlockedExternalProtocolHandlerConstructor, },
{ NS_PREFETCHSERVICE_CLASSNAME, NS_PREFETCHSERVICE_CID, NS_PREFETCHSERVICE_CONTRACTID,
nsPrefetchServiceConstructor, },
{ "Local Application Handler App", NS_LOCALHANDLERAPP_CID,
NS_LOCALHANDLERAPP_CONTRACTID, nsLocalHandlerAppConstructor, },
#if defined(XP_MAC) || defined(XP_MACOSX)
{ "Internet Config Service", NS_INTERNETCONFIGSERVICE_CID, NS_INTERNETCONFIGSERVICE_CONTRACTID,
nsInternetConfigServiceConstructor, },
#endif
// session history
{ "nsSHEntry", NS_SHENTRY_CID,
NS_SHENTRY_CONTRACTID, nsSHEntryConstructor },

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

@ -137,13 +137,13 @@ nsMimeTypeArray::NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn)
getter_AddRefs(mimeInfo));
if (mimeInfo) {
// Now we check whether we can really claim to support this type
nsMIMEInfoHandleAction action = nsIMIMEInfo::saveToDisk;
nsHandlerInfoAction action = nsIHandlerInfo::saveToDisk;
mimeInfo->GetPreferredAction(&action);
if (action != nsIMIMEInfo::handleInternally) {
PRBool hasHelper = PR_FALSE;
mimeInfo->GetHasDefaultHandler(&hasHelper);
if (!hasHelper) {
nsCOMPtr<nsIFile> helper;
nsCOMPtr<nsIHandlerApp> helper;
mimeInfo->GetPreferredApplicationHandler(getter_AddRefs(helper));
if (!helper) {
// mime info from the OS may not have a PreferredApplicationHandler

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

@ -466,8 +466,10 @@ nsHelperAppDialog.prototype = {
this.initDefaultApp();
// Fill application name textbox.
if (this.chosenApp && this.chosenApp.path) {
this.dialogElement( "appPath" ).value = this.getPath(this.chosenApp);
if (this.chosenApp && this.chosenApp.executable &&
this.chosenApp.executable.path) {
this.dialogElement( "appPath" ).value =
this.getPath(this.chosenApp.executable);
}
var useDefault = this.dialogElement( "useSystemDefault" );;
@ -517,10 +519,10 @@ nsHelperAppDialog.prototype = {
// First, see if one was chosen via the Choose... button.
if ( result ) {
// Verify that the user didn't type in something different later.
if ( typed != result.path ) {
if ( typed != result.executable.path ) {
// Use what was typed in.
try {
result.QueryInterface( Components.interfaces.nsILocalFile ).initWithPath( typed );
result.executable.QueryInterface( Components.interfaces.nsILocalFile ).initWithPath( typed );
} catch( e ) {
// Invalid path was typed.
result = null;
@ -528,10 +530,15 @@ nsHelperAppDialog.prototype = {
}
} else {
// The user didn't use the Choose... button, try using what they typed in.
result = Components.classes[ "@mozilla.org/file/local;1" ]
var localFile = Components.classes[ "@mozilla.org/file/local;1" ]
.createInstance( Components.interfaces.nsILocalFile );
try {
result.initWithPath( typed );
localFile.initWithPath( typed );
result = Components.classes[
"@mozilla.org/uriloader/local-handler-app;1"].
createInstance(Components.interfaces.nsILocalHandlerApp);
result.executable = localFile;
} catch( e ) {
result = null;
}
@ -591,10 +598,9 @@ nsHelperAppDialog.prototype = {
needUpdate = this.mLauncher.MIMEInfo.preferredAction != this.nsIMIMEInfo.useHelperApp || this.appChanged();
if ( needUpdate ) {
this.mLauncher.MIMEInfo.preferredAction = this.nsIMIMEInfo.useHelperApp;
// App may have changed - Update application and description
// App may have changed - Update application
var app = this.helperAppChoice();
this.mLauncher.MIMEInfo.preferredApplicationHandler = app;
this.mLauncher.MIMEInfo.applicationDescription = "";
}
}
// Only care about the state of "always ask" if this dialog wasn't forced
@ -635,7 +641,7 @@ nsHelperAppDialog.prototype = {
// Verify typed app path, if necessary.
if ( this.dialogElement( "openUsing" ).selected ) {
var helperApp = this.helperAppChoice();
if ( !helperApp || !helperApp.exists() ) {
if ( !helperApp || !helperApp.executable || !helperApp.exists() ) {
// Show alert and try again.
var msg = this.replaceInsert( this.getString( "badApp" ), 1, this.dialogElement( "appPath" ).value );
var svc = Components.classes[ "@mozilla.org/embedcomp/prompt-service;1" ]
@ -731,9 +737,15 @@ nsHelperAppDialog.prototype = {
if ( fp.show() == nsIFilePicker.returnOK && fp.file ) {
// Remember the file they chose to run.
this.chosenApp = fp.file;
var localHandler = Components.classes[
"@mozilla.org/uriloader/local-handler-app;1"].
createInstance(Components.interfaces.nsILocalHandlerApp);
localHandler.executable = fp.file;
this.chosenApp = localHandler;
// Update dialog.
this.dialogElement( "appPath" ).value = this.getPath(this.chosenApp);
this.dialogElement( "appPath" ).value =
this.getPath(this.chosenApp.executable);
}
},

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

@ -445,8 +445,11 @@ nsProgressDialog.prototype = {
this.setValue( "sourceLabel", this.getString( "openingSource" ) );
// Target is the "preferred" application. Hide if empty.
if ( this.MIMEInfo && this.MIMEInfo.preferredApplicationHandler ) {
var appName = this.MIMEInfo.preferredApplicationHandler.leafName;
if ( this.MIMEInfo &&
this.MIMEInfo.preferredApplicationHandler &&
this.MIMEInfo.preferredApplicationHandler.executable ) {
var appName =
this.MIMEInfo.preferredApplicationHandler.executable.leafName;
if ( appName == null || appName.length == 0 ) {
this.hide( "targetRow" );
} else {

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

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Mosedale <dmose@mozilla.org>
*
* 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
@ -35,27 +36,89 @@
*
* ***** END LICENSE BLOCK ***** */
/**
* An nsIMIMEInfo gives a user access to mime information.
* there is a one-to-many relationship between MIME types
* and file extensions. This means that a MIMEInfo object
* may have multiple file extensions associated with it.
* However, the reverse is not true.
*
* MIMEInfo objects are generally retrieved from the MIME Service
* @see nsIMIMEService
*/
#include "nsISupports.idl"
interface nsIURI;
interface nsIFile;
interface nsIUTF8StringEnumerator;
interface nsIHandlerApp;
typedef long nsMIMEInfoHandleAction;
typedef long nsHandlerInfoAction;
[scriptable, uuid(1448b42f-cf0d-466e-9a15-64e876ebe857)]
interface nsIMIMEInfo : nsISupports {
/**
* nsIHandlerInfo gives access to the information about how a given protocol
* scheme or MIME-type is handled.
*/
[scriptable, uuid(feaa5a46-45aa-4124-8e9e-bc23d517c2d4)]
interface nsIHandlerInfo : nsISupports {
/**
* A human readable description of the handler type
*/
attribute AString description;
/**
* The application the user has said they want associated with this content
* type. This is not always guaranteed to be set!!
*/
attribute nsIHandlerApp preferredApplicationHandler;
/**
* Indicates whether a default application handler exists,
* i.e. whether launchWithFile with action = useSystemDefault is possible
* and defaultDescription will contain usable information.
*/
readonly attribute boolean hasDefaultHandler;
/**
* A pretty name description of the associated default application. Only
* usable if hasDefaultHandler is true.
*/
readonly attribute AString defaultDescription;
/**
* Launches the application with the specified file, in a way that
* depends on the value of preferredAction. preferredAction must be
* useHelperApp or useSystemDefault.
*
* @param aFile The file to launch this application with.
*
* @throw NS_ERROR_INVALID_ARG if action is not valid for this function.
* Other exceptions may be thrown.
*/
void launchWithFile(in nsIFile aFile);
/**
* preferredAction is how the user specified they would like to handle
* this content type: save to disk, use specified helper app, use OS
* default handler or handle using navigator; possible value constants
* listed below
*/
attribute nsHandlerInfoAction preferredAction;
const long saveToDisk = 0;
const long alwaysAsk = 1;
const long useHelperApp = 2;
const long handleInternally = 3;
const long useSystemDefault = 4;
/**
* alwaysAskBeforeHandling: if true, we should always give the user a
* dialog asking how to dispose of this content.
*/
attribute boolean alwaysAskBeforeHandling;
};
/**
* nsIMIMEInfo extends nsIHandlerInfo with a bunch of information specific to
* MIME content-types. There is a one-to-many relationship between MIME types
* and file extensions. This means that a MIMEInfo object may have multiple
* file extensions associated with it. However, the reverse is not true.
*
* MIMEInfo objects are generally retrieved from the MIME Service
* @see nsIMIMEService
*/
[scriptable, uuid(ba01eb13-c2fd-4652-94f8-b33c61e6d77e)]
interface nsIMIMEInfo : nsIHandlerInfo {
/**
* Gives you an array of file types associated with this type.
*
@ -97,13 +160,6 @@ interface nsIMIMEInfo : nsISupports {
*/
readonly attribute ACString MIMEType;
/**
* A human readable description of the MIME info.
*
* @return The description
*/
attribute AString description;
/**
* Mac Type and creator types
*/
@ -111,68 +167,56 @@ interface nsIMIMEInfo : nsISupports {
attribute PRUint32 macCreator;
/**
* Returns whether or not these two MIME infos are logically
* equivalent maintaining the one-to-many relationship between
* MIME types and file extensions.
* Returns whether or not these two nsIMIMEInfos are logically
* equivalent.
*
* @returns TRUE if the two are considered equal
* @returns PR_TRUE if the two are considered equal
*/
boolean equals(in nsIMIMEInfo aMIMEInfo);
/**
* Returns a nsIFile that points to the application the user has said
* they want associated with this content type. This is not always
* guaranteed to be set!!
*/
attribute nsIFile preferredApplicationHandler;
/**
* A pretty name description of the preferred application.
*/
attribute AString applicationDescription;
/**
* Indicates whether a default application handler exists,
* i.e. whether launchWithFile with action = useSystemDefault is possible
* and applicationDescription will contain usable information.
*/
readonly attribute boolean hasDefaultHandler;
/**
* A pretty name description of the associated default application. Only
* usable if hasDefaultHandler is true.
*/
readonly attribute AString defaultDescription;
/**
* Launches the application with the specified file, in a way that
* depends on the value of preferredAction. preferredAction must be
* useHelperApp or useSystemDefault.
*
* @param aFile The file to launch this application with.
*
* @throw NS_ERROR_INVALID_ARG if action is not valid for this function.
* Other exceptions may be thrown.
*/
void launchWithFile(in nsIFile aFile);
const long saveToDisk = 0;
const long alwaysAsk = 1;
const long useHelperApp = 2;
const long handleInternally = 3;
const long useSystemDefault = 4;
/**
* preferredAction is how the user specified they would like to handle
* this content type: save to disk, use specified helper app, use OS
* default handler or handle using navigator.
*/
attribute nsMIMEInfoHandleAction preferredAction;
/**
* alwaysAskBeforeHandling: if true, we should always give the user a
* dialog asking how to dispose of this content.
*/
attribute boolean alwaysAskBeforeHandling;
};
/**
* nsIHandlerApp represents an external application that can handle content
* of some sort (either a MIME-type or a protocol). Note that for theoretical
* cleanliness, nsI{Local,Web}HandlerApp really ought to inherit from
* nsIHandlerApp. After that's done, we should also try and make
* nsIWebContentHandlerInfo inherit from or possibly be replaced by
* nsIWebHandlerApp.
*/
[scriptable, uuid(08a543dc-081f-4933-b325-252cf68d6ad9)]
interface nsIHandlerApp : nsISupports {
/**
* Human readable name for the handler
*/
attribute AString name;
};
/**
* nsILocalHandlerApp is a local OS-level executable
*/
[scriptable, uuid(e21f3d75-9103-490e-bfb9-1bf09cc3f103)]
interface nsILocalHandlerApp: nsISupports {
/**
* Pointer to the executable file used to handle content
*/
attribute nsIFile executable;
};
/**
* nsIWebHandlerApp is a web-based handler, as speced by the WhatWG HTML5
* draft. Currently, only GET-based handlers are supported. At some point,
* we probably want to work with WhatWG to spec out and implement POST-based
* handlers as well.
*/
[scriptable, uuid(065cd099-2f71-4ac8-9dab-17fc079e9647)]
interface nsIWebHandlerApp: nsISupports {
/**
* Template used to construct the URI to GET. Template is expected to have
* a %s in it, and the escaped URI to be handled is inserted in place of
* that %s, as per the HTML5 spec.
*/
attribute AUTF8String uriTemplate;
};

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

@ -166,8 +166,8 @@ HelperApps.prototype = {
entry.saveToDisk = false;
entry.useSystemDefault = false;
entry.handleInternal = false;
entry.appPath = aMIMEInfo.preferredApplicationHandler.path;
entry.appDisplayName = aMIMEInfo.applicationDescription;
entry.appPath = aMIMEInfo.preferredApplicationHandler.executable.path;
entry.appDisplayName = aMIMEInfo.preferredApplicationHandler.name;
}
// Do RDF magic.

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

@ -25,6 +25,7 @@
# Scott MacGregor <mscott@netscape.com>
# Ben Goodger <ben@bengoodger.com> (2.0)
# Fredrik Holmqvist <thesuckiestemail@yahoo.se>
# Dan Mosedale <dmose@mozilla.org>
#
# 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
@ -683,9 +684,11 @@ nsUnknownContentTypeDialog.prototype = {
var otherHandler = this.dialogElement("otherHandler");
// Fill application name textbox.
if (this.chosenApp && this.chosenApp.path) {
otherHandler.setAttribute("path", this.getPath(this.chosenApp));
otherHandler.label = this.chosenApp.leafName;
if (this.chosenApp && this.chosenApp.executable &&
this.chosenApp.executable.path) {
otherHandler.setAttribute("path",
this.getPath(this.chosenApp.executable));
otherHandler.label = this.chosenApp.executable.leafName;
otherHandler.hidden = false;
}
@ -808,10 +811,9 @@ nsUnknownContentTypeDialog.prototype = {
needUpdate = this.mLauncher.MIMEInfo.preferredAction != this.nsIMIMEInfo.useHelperApp || this.appChanged();
if (needUpdate) {
this.mLauncher.MIMEInfo.preferredAction = this.nsIMIMEInfo.useHelperApp;
// App may have changed - Update application and description
// App may have changed - Update application
var app = this.helperAppChoice();
this.mLauncher.MIMEInfo.preferredApplicationHandler = app;
this.mLauncher.MIMEInfo.applicationDescription = "";
}
}
// We will also need to update if the "always ask" flag has changed.
@ -844,7 +846,8 @@ nsUnknownContentTypeDialog.prototype = {
// Verify typed app path, if necessary.
if (this.useOtherHandler) {
var helperApp = this.helperAppChoice();
if (!helperApp || !helperApp.exists()) {
if (!helperApp || !helperApp.executable ||
!helperApp.executable.exists()) {
// Show alert and try again.
var bundle = this.dialogElement("strings");
var msg = bundle.getFormattedString("badApp", [this.dialogElement("otherHandler").path]);
@ -959,12 +962,17 @@ nsUnknownContentTypeDialog.prototype = {
this.dialogElement("modeDeck").setAttribute("selectedIndex", "0");
// Remember the file they chose to run.
this.chosenApp = fp.file;
var localHandlerApp =
Components.classes["@mozilla.org/uriloader/local-handler-app;1"].
createInstance(Components.interfaces.nsILocalHandlerApp);
localHandlerApp.executable = fp.file;
this.chosenApp = localHandlerApp;
// Update dialog.
var otherHandler = this.dialogElement("otherHandler");
otherHandler.removeAttribute("hidden");
otherHandler.setAttribute("path", this.getPath(this.chosenApp));
otherHandler.label = this.chosenApp.leafName;
otherHandler.setAttribute("path", this.getPath(this.chosenApp.executable));
otherHandler.label = this.chosenApp.executable.leafName;
this.dialogElement("openHandler").selectedIndex = 1;
this.dialogElement("openHandler").setAttribute("lastSelectedItemID", "otherHandler");

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

@ -138,6 +138,7 @@ CPPSRCS = \
nsExternalHelperAppService.cpp \
nsExternalProtocolHandler.cpp \
nsMIMEInfoImpl.cpp \
nsHandlerAppImpl.cpp \
$(OSHELPER) \
$(NULL)

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

@ -46,11 +46,17 @@
NS_IMETHODIMP
nsMIMEInfoMac::LaunchWithFile(nsIFile* aFile)
{
nsIFile* application;
nsCOMPtr<nsIFile> application;
if (mPreferredAction == useHelperApp)
application = mPreferredApplication;
else if (mPreferredAction == useSystemDefault)
if (mPreferredAction == useHelperApp) {
nsresult rv;
nsCOMPtr<nsILocalHandlerApp> localHandlerApp =
do_QueryInterface(mPreferredApplication, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = localHandlerApp->GetExecutable(getter_AddRefs(application));
NS_ENSURE_SUCCESS(rv, rv);
} else if (mPreferredAction == useSystemDefault)
application = mDefaultApplication;
else
return NS_ERROR_INVALID_ARG;

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

@ -22,6 +22,7 @@
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
* Dan Mosedale <dmose@mozilla.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -67,5 +68,12 @@ nsIExternalHelperAppService
#define NS_BLOCKEDEXTERNALPROTOCOLHANDLER_CID \
{ 0x9fa83ce7, 0xd0ab, 0x4ed3, {0x93, 0x8e, 0xaf, 0xaf, 0xee, 0x43, 0x56, 0x70 } }
/* bc0017e3-2438-47be-a567-41db58f17627 */
#define NS_LOCALHANDLERAPP_CID \
{ 0xbc0017e3, 0x2438, 0x47be, {0xa5, 0x67, 0x41, 0xdb, 0x58, 0xf1, 0x76, 0x27 } }
#define NS_LOCALHANDLERAPP_CONTRACTID \
"@mozilla.org/uriloader/local-handler-app;1"
%}

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

@ -120,6 +120,9 @@
#include "nsCRT.h"
#include "nsMIMEInfoImpl.h"
#include "nsHandlerAppImpl.h"
#ifdef PR_LOGGING
PRLogModuleInfo* nsExternalHelperAppService::mLog = nsnull;
#endif
@ -566,7 +569,10 @@ nsresult nsExternalHelperAppService::InitDataSource()
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_ALWAYSASK),
getter_AddRefs(kNC_AlwaysAsk));
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_PRETTYNAME),
getter_AddRefs(kNC_PrettyName));
getter_AddRefs(kNC_PrettyName));
rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_URITEMPLATE),
getter_AddRefs(kNC_UriTemplate));
}
mDataSourceInitialized = PR_TRUE;
@ -715,8 +721,9 @@ NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension(const nsACSt
}
#ifdef MOZ_RDF
nsresult nsExternalHelperAppService::FillTopLevelProperties(nsIRDFResource * aContentTypeNodeResource,
nsIRDFService * aRDFService, nsIMIMEInfo * aMIMEInfo)
nsresult nsExternalHelperAppService::FillMIMEExtensionProperties(
nsIRDFResource * aContentTypeNodeResource, nsIRDFService * aRDFService,
nsIMIMEInfo * aMIMEInfo)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIRDFNode> target;
@ -726,12 +733,7 @@ nsresult nsExternalHelperAppService::FillTopLevelProperties(nsIRDFResource * aCo
rv = InitDataSource();
if (NS_FAILED(rv)) return NS_OK;
// set the pretty name description, if nonempty
FillLiteralValueFromTarget(aContentTypeNodeResource,kNC_Description, &stringValue);
if (stringValue && *stringValue)
aMIMEInfo->SetDescription(nsDependentString(stringValue));
// now iterate over all the file type extensions...
// iterate over all the file type extensions...
nsCOMPtr<nsISimpleEnumerator> fileExtensions;
mOverRideDataSource->GetTargets(aContentTypeNodeResource, kNC_FileExtensions, PR_TRUE, getter_AddRefs(fileExtensions));
@ -787,10 +789,9 @@ nsresult nsExternalHelperAppService::FillLiteralValueFromTarget(nsIRDFResource *
return rv;
}
nsresult nsExternalHelperAppService::FillContentHandlerProperties(const char * aContentType,
nsIRDFResource * aContentTypeNodeResource,
nsIRDFService * aRDFService,
nsIMIMEInfo * aMIMEInfo)
nsresult nsExternalHelperAppService::FillContentHandlerProperties(
const char * aContentType, const char * aTypeNodePrefix,
nsIRDFService * aRDFService, nsIHandlerInfo * aHandlerInfo)
{
nsCOMPtr<nsIRDFNode> target;
nsCOMPtr<nsIRDFLiteral> literal;
@ -800,7 +801,8 @@ nsresult nsExternalHelperAppService::FillContentHandlerProperties(const char * a
rv = InitDataSource();
if (NS_FAILED(rv)) return rv;
nsCAutoString contentTypeHandlerNodeName(NC_CONTENT_NODE_HANDLER_PREFIX);
nsCAutoString contentTypeHandlerNodeName(aTypeNodePrefix);
contentTypeHandlerNodeName.Append(NC_HANDLER_SUFFIX);
contentTypeHandlerNodeName.Append(aContentType);
nsCOMPtr<nsIRDFResource> contentTypeHandlerNodeResource;
@ -808,56 +810,79 @@ nsresult nsExternalHelperAppService::FillContentHandlerProperties(const char * a
NS_ENSURE_TRUE(contentTypeHandlerNodeResource, NS_ERROR_FAILURE); // that's not good! we have an error in the rdf file
// now process the application handler information
aMIMEInfo->SetPreferredAction(nsIMIMEInfo::useHelperApp);
aHandlerInfo->SetPreferredAction(nsIHandlerInfo::useHelperApp);
// save to disk
FillLiteralValueFromTarget(contentTypeHandlerNodeResource,kNC_SaveToDisk, &stringValue);
NS_NAMED_LITERAL_STRING(trueString, "true");
NS_NAMED_LITERAL_STRING(falseString, "false");
if (stringValue && trueString.Equals(stringValue))
aMIMEInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk);
aHandlerInfo->SetPreferredAction(nsIHandlerInfo::saveToDisk);
// use system default
FillLiteralValueFromTarget(contentTypeHandlerNodeResource,kNC_UseSystemDefault, &stringValue);
if (stringValue && trueString.Equals(stringValue))
aMIMEInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault);
aHandlerInfo->SetPreferredAction(nsIHandlerInfo::useSystemDefault);
// handle internal
FillLiteralValueFromTarget(contentTypeHandlerNodeResource,kNC_HandleInternal, &stringValue);
if (stringValue && trueString.Equals(stringValue))
aMIMEInfo->SetPreferredAction(nsIMIMEInfo::handleInternally);
aHandlerInfo->SetPreferredAction(nsIHandlerInfo::handleInternally);
// always ask
FillLiteralValueFromTarget(contentTypeHandlerNodeResource,kNC_AlwaysAsk, &stringValue);
// Only skip asking if we are absolutely sure the user does not want
// to be asked. Any sort of bofus data should mean we ask.
aMIMEInfo->SetAlwaysAskBeforeHandling(!stringValue ||
aHandlerInfo->SetAlwaysAskBeforeHandling(!stringValue ||
!falseString.Equals(stringValue));
// now digest the external application information
nsCAutoString externalAppNodeName (NC_CONTENT_NODE_EXTERNALAPP_PREFIX);
nsCAutoString externalAppNodeName(aTypeNodePrefix);
externalAppNodeName.AppendLiteral(NC_EXTERNALAPP_SUFFIX);
externalAppNodeName.Append(aContentType);
nsCOMPtr<nsIRDFResource> externalAppNodeResource;
aRDFService->GetResource(externalAppNodeName, getter_AddRefs(externalAppNodeResource));
// Clear out any possibly set preferred application, to match the datasource
aMIMEInfo->SetApplicationDescription(EmptyString());
aMIMEInfo->SetPreferredApplicationHandler(nsnull);
aHandlerInfo->SetPreferredApplicationHandler(nsnull);
if (externalAppNodeResource)
{
FillLiteralValueFromTarget(externalAppNodeResource, kNC_PrettyName, &stringValue);
if (stringValue)
aMIMEInfo->SetApplicationDescription(nsDependentString(stringValue));
const PRUnichar * appName;
FillLiteralValueFromTarget(externalAppNodeResource, kNC_PrettyName,
&appName);
// if we've got a path name, this must be a local app
FillLiteralValueFromTarget(externalAppNodeResource, kNC_Path, &stringValue);
if (stringValue && stringValue[0])
{
nsCOMPtr<nsIFile> application;
GetFileTokenForPath(stringValue, getter_AddRefs(application));
if (application)
aMIMEInfo->SetPreferredApplicationHandler(application);
if (application) {
nsLocalHandlerApp *handlerApp(new nsLocalHandlerApp(appName, application));
if (!handlerApp) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = aHandlerInfo->SetPreferredApplicationHandler(handlerApp);
}
} else {
// if we got here, there's no path name in the RDF graph, so this must
// be a web app
FillLiteralValueFromTarget(externalAppNodeResource, kNC_UriTemplate,
&stringValue);
if (stringValue && stringValue[0]) {
nsWebHandlerApp *handlerApp(new nsWebHandlerApp(appName,
NS_ConvertUTF16toUTF8(stringValue)));
if (!handlerApp) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = aHandlerInfo->SetPreferredApplicationHandler(handlerApp);
} else {
return NS_ERROR_FAILURE; // no path name _and_ no uri template
}
}
}
@ -903,7 +928,8 @@ PRBool nsExternalHelperAppService::MIMETypeIsInDataSource(const char * aContentT
return PR_FALSE;
}
nsresult nsExternalHelperAppService::GetMIMEInfoForMimeTypeFromDS(const nsACString& aContentType, nsIMIMEInfo * aMIMEInfo)
nsresult nsExternalHelperAppService::FillMIMEInfoForMimeTypeFromDS(
const nsACString& aContentType, nsIMIMEInfo * aMIMEInfo)
{
#ifdef MOZ_RDF
NS_ENSURE_ARG_POINTER(aMIMEInfo);
@ -918,34 +944,94 @@ nsresult nsExternalHelperAppService::GetMIMEInfoForMimeTypeFromDS(const nsACStri
nsCOMPtr<nsIRDFService> rdf = do_GetService(kRDFServiceCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Build uri for the mimetype resource.
nsCAutoString contentTypeNodeName(NC_CONTENT_NODE_PREFIX);
nsCAutoString contentType(aContentType);
ToLowerCase(contentType);
contentTypeNodeName.Append(contentType);
// get lowercase typename & uri for the handlertype resource.
nsCAutoString typeNodeName(NC_CONTENT_NODE_PREFIX);
nsCAutoString type(aContentType);
ToLowerCase(type);
typeNodeName.Append(type);
// Get the mime type resource.
nsCOMPtr<nsIRDFResource> contentTypeNodeResource;
rv = rdf->GetResource(contentTypeNodeName, getter_AddRefs(contentTypeNodeResource));
// Get the handler type resource.
nsCOMPtr<nsIRDFResource> typeNodeResource;
rv = rdf->GetResource(typeNodeName, getter_AddRefs(typeNodeResource));
NS_ENSURE_SUCCESS(rv, rv);
// we need a way to determine if this content type resource is really in the graph or not...
// ...Test that there's a #value arc from the mimetype resource to the mimetype literal string.
nsCOMPtr<nsIRDFLiteral> mimeLiteral;
NS_ConvertUTF8toUTF16 mimeType(contentType);
rv = rdf->GetLiteral( mimeType.get(), getter_AddRefs( mimeLiteral ) );
// fill in MIME-specific extension info
rv = FillMIMEExtensionProperties(typeNodeResource, rdf, aMIMEInfo);
NS_ENSURE_SUCCESS(rv, rv);
return FillHandlerInfoForTypeFromDS(typeNodeResource.get(), type, rdf,
NC_CONTENT_NODE_PREFIX, aMIMEInfo);
#else
return NS_ERROR_NOT_AVAILABLE;
#endif
}
nsresult nsExternalHelperAppService::FillProtoInfoForSchemeFromDS(
const nsACString& aType, nsIHandlerInfo * aHandlerInfo)
{
#ifdef MOZ_RDF
NS_ENSURE_ARG_POINTER(aHandlerInfo);
nsresult rv = InitDataSource();
if (NS_FAILED(rv)) return rv;
// can't do anything if we have no datasource...
if (!mOverRideDataSource)
return NS_ERROR_FAILURE;
// Get the RDF service.
nsCOMPtr<nsIRDFService> rdf = do_GetService(kRDFServiceCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// get lowercase typename & get uri for the handlertype resource.
nsCAutoString typeNodeName(NC_SCHEME_NODE_PREFIX);
nsCAutoString type(aType);
ToLowerCase(type);
typeNodeName.Append(type);
// Get the handler type resource.
nsCOMPtr<nsIRDFResource> typeNodeResource;
rv = rdf->GetResource(typeNodeName, getter_AddRefs(typeNodeResource));
NS_ENSURE_SUCCESS(rv, rv);
return FillHandlerInfoForTypeFromDS(typeNodeResource.get(), type, rdf,
NC_SCHEME_NODE_PREFIX, aHandlerInfo);
#else
return NS_ERROR_NOT_AVAILABLE;
#endif
}
nsresult nsExternalHelperAppService::FillHandlerInfoForTypeFromDS(
nsIRDFResource *aTypeNodeResource, const nsCAutoString &aType,
nsIRDFService *rdf, const char *aTypeNodePrefix,
nsIHandlerInfo * aHandlerInfo)
{
#ifdef MOZ_RDF
// we need a way to determine if this type resource is really in the graph
// or not... Test that there's a #value arc from the type resource to the
// type literal string.
nsCOMPtr<nsIRDFLiteral> typeLiteral;
NS_ConvertUTF8toUTF16 UTF16Type(aType);
nsresult rv = rdf->GetLiteral( UTF16Type.get(),
getter_AddRefs( typeLiteral ) );
NS_ENSURE_SUCCESS(rv, rv);
PRBool exists = PR_FALSE;
rv = mOverRideDataSource->HasAssertion(contentTypeNodeResource, kNC_Value, mimeLiteral, PR_TRUE, &exists );
rv = mOverRideDataSource->HasAssertion(aTypeNodeResource, kNC_Value,
typeLiteral, PR_TRUE, &exists );
if (NS_SUCCEEDED(rv) && exists)
{
// fill the mimeinfo in based on the values from the data source
rv = FillTopLevelProperties(contentTypeNodeResource, rdf, aMIMEInfo);
NS_ENSURE_SUCCESS(rv, rv);
rv = FillContentHandlerProperties(contentType.get(), contentTypeNodeResource, rdf, aMIMEInfo);
// fill in the handlerinfo based on the values from the data source
// set the pretty name description, if nonempty
const PRUnichar *stringValue;
FillLiteralValueFromTarget(aTypeNodeResource, kNC_Description,
&stringValue);
if (stringValue && *stringValue)
aHandlerInfo->SetDescription(nsDependentString(stringValue));
rv = FillContentHandlerProperties(aType.get(), aTypeNodePrefix,
rdf, aHandlerInfo);
} // if we have a node in the graph for this content type
// If we had success, but entry doesn't exist, we don't want to return success
@ -959,14 +1045,15 @@ nsresult nsExternalHelperAppService::GetMIMEInfoForMimeTypeFromDS(const nsACStri
#endif /* MOZ_RDF */
}
nsresult nsExternalHelperAppService::GetMIMEInfoForExtensionFromDS(const nsACString& aFileExtension, nsIMIMEInfo * aMIMEInfo)
nsresult nsExternalHelperAppService::FillMIMEInfoForExtensionFromDS(
const nsACString& aFileExtension, nsIMIMEInfo * aMIMEInfo)
{
nsCAutoString type;
PRBool found = GetTypeFromDS(aFileExtension, type);
if (!found)
return NS_ERROR_NOT_AVAILABLE;
return GetMIMEInfoForMimeTypeFromDS(type, aMIMEInfo);
return FillMIMEInfoForMimeTypeFromDS(type, aMIMEInfo);
}
PRBool nsExternalHelperAppService::GetTypeFromDS(const nsACString& aExtension,
@ -1051,16 +1138,17 @@ nsresult nsExternalHelperAppService::GetFileTokenForPath(const PRUnichar * aPlat
NS_IMETHODIMP nsExternalHelperAppService::ExternalProtocolHandlerExists(const char * aProtocolScheme,
PRBool * aHandlerExists)
{
// check for web-based handler
nsCAutoString uriTemplate;
nsresult rv = GetWebProtocolHandlerURITemplate(
nsDependentCString(aProtocolScheme), uriTemplate);
// if we've got handler info in the datasource, that means that at least one
// web handler exists
nsCOMPtr<nsIHandlerInfo> handlerInfo;
nsresult rv = GetProtocolHandlerInfo(
nsDependentCString(aProtocolScheme), getter_AddRefs(handlerInfo));
if (NS_SUCCEEDED(rv)) {
*aHandlerExists = PR_TRUE;
return NS_OK;
}
// fall back on an os-based handler
// if not, fall back on an os-based handler
return OSProtocolHandlerExists(aProtocolScheme, aHandlerExists);
}
@ -1375,39 +1463,32 @@ nsresult nsExternalHelperAppService::ExpungeTemporaryFiles()
}
nsresult
nsExternalHelperAppService::GetWebProtocolHandlerURITemplate(const nsACString &aScheme,
nsACString &aUriTemplate)
nsExternalHelperAppService::GetProtocolHandlerInfo(const nsACString &aScheme,
nsIHandlerInfo **aHandlerInfo)
{
nsresult rv;
nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID,
&rv);
NS_ENSURE_SUCCESS(rv, rv);
// before we expose this to the UI, we need sort out our strategy re
// XXX before we expose this to the UI, we need sort out our strategy re
// the "warning" and "exposed" prefs
// XXX enterprise customers should be able to turn this support off with a
// single master pref (maybe use one of the "exposed" prefs here?)
// do we have an automatic handler for this protocol?
nsCAutoString autoTemplatePref("network.protocol-handler.web.auto.");
autoTemplatePref += aScheme;
nsCAutoString autoTemplate;
rv = prefBranch->GetCharPref(autoTemplatePref.get(),
getter_Copies(autoTemplate));
// if so, return it.
if (NS_SUCCEEDED(rv)) {
aUriTemplate.Assign(autoTemplate);
return NS_OK;
// nsIMIMEInfo is a superset of nsIHandlerInfo. Furthermore, nsMimeInfoImpl
// and subclasses have lots of good platform specific-knowledge of local
// applications which we might need later. For now, just use nsMIMEInfoImpl
// instead of implementating a separate nsIHandlerInfo object.
nsMIMEInfoImpl *mimeInfo = new nsMIMEInfoImpl;
if (!mimeInfo) {
return NS_ERROR_OUT_OF_MEMORY;
}
// XXX since there's no automatic handler, if we have any choices, offer them
// up as well as including the option to make one of the choices automatic.
// do so by returning "about:protoHandlerChooser?uri=%s" as the template or
// perhaps by opening a dialog
return NS_ERROR_FAILURE;
NS_ADDREF(*aHandlerInfo = mimeInfo);
nsresult rv = FillProtoInfoForSchemeFromDS(aScheme, *aHandlerInfo);
if (NS_FAILED(rv)) {
NS_RELEASE(*aHandlerInfo);
return rv;
}
return NS_OK;
}
// XPCOM profile change observer
@ -1894,7 +1975,7 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest *request, nsISuppo
* test here is as close as possible to what will really be
* happening if we decide to execute
*/
nsCOMPtr<nsIFile> prefApp;
nsCOMPtr<nsIHandlerApp> prefApp;
mMimeInfo->GetPreferredApplicationHandler(getter_AddRefs(prefApp));
if (action != nsIMIMEInfo::useHelperApp || !prefApp) {
nsCOMPtr<nsIFile> fileToTest;
@ -2166,7 +2247,7 @@ nsresult nsExternalAppHandler::ExecuteDesiredAction()
nsresult rv = NS_OK;
if (mProgressListenerInitialized && !mCanceled)
{
nsMIMEInfoHandleAction action = nsIMIMEInfo::saveToDisk;
nsHandlerInfoAction action = nsIMIMEInfo::saveToDisk;
mMimeInfo->GetPreferredAction(&action);
if (action == nsIMIMEInfo::useHelperApp ||
action == nsIMIMEInfo::useSystemDefault)
@ -2521,8 +2602,11 @@ NS_IMETHODIMP nsExternalAppHandler::LaunchWithApplication(nsIFile * aApplication
ProcessAnyRefreshTags();
mReceivedDispositionInfo = PR_TRUE;
if (mMimeInfo && aApplication)
mMimeInfo->SetPreferredApplicationHandler(aApplication);
if (mMimeInfo && aApplication) {
nsLocalHandlerApp *handlerApp(new nsLocalHandlerApp(EmptyString(),
aApplication));
mMimeInfo->SetPreferredApplicationHandler(handlerApp);
}
// Now check if the file is local, in which case we won't bother with saving
// it to a temporary directory and just launch it from where it is
@ -2609,7 +2693,7 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason)
// But if we haven't received disposition info yet, then we're
// here because the user cancelled the helper app dialog.
// Delete the file in this case.
nsMIMEInfoHandleAction action = nsIMIMEInfo::saveToDisk;
nsHandlerInfoAction action = nsIMIMEInfo::saveToDisk;
mMimeInfo->GetPreferredAction(&action);
if (mTempFile &&
(!mReceivedDispositionInfo || action != nsIMIMEInfo::saveToDisk))
@ -2748,7 +2832,7 @@ NS_IMETHODIMP nsExternalHelperAppService::GetFromTypeAndExtension(const nsACStri
// (2) Now, let's see if we can find something in our datasource
// This will not overwrite the OS information that interests us
// (i.e. default application, default app. description)
nsresult rv = GetMIMEInfoForMimeTypeFromDS(typeToUse, *_retval);
nsresult rv = FillMIMEInfoForMimeTypeFromDS(typeToUse, *_retval);
found = found || NS_SUCCEEDED(rv);
LOG(("Data source: Via type: retval 0x%08x\n", rv));
@ -2756,7 +2840,7 @@ NS_IMETHODIMP nsExternalHelperAppService::GetFromTypeAndExtension(const nsACStri
if (!found || NS_FAILED(rv)) {
// No type match, try extension match
if (!aFileExt.IsEmpty()) {
rv = GetMIMEInfoForExtensionFromDS(aFileExt, *_retval);
rv = FillMIMEInfoForExtensionFromDS(aFileExt, *_retval);
LOG(("Data source: Via ext: retval 0x%08x\n", rv));
found = found || NS_SUCCEEDED(rv);
}
@ -2775,11 +2859,11 @@ NS_IMETHODIMP nsExternalHelperAppService::GetFromTypeAndExtension(const nsACStri
*/
if (!typeToUse.Equals(APPLICATION_OCTET_STREAM, nsCaseInsensitiveCStringComparator()))
#endif
rv = GetMIMEInfoForMimeTypeFromExtras(typeToUse, *_retval);
rv = FillMIMEInfoForMimeTypeFromExtras(typeToUse, *_retval);
LOG(("Searched extras (by type), rv 0x%08X\n", rv));
// If that didn't work out, try file extension from extras
if (NS_FAILED(rv) && !aFileExt.IsEmpty()) {
rv = GetMIMEInfoForExtensionFromExtras(aFileExt, *_retval);
rv = FillMIMEInfoForExtensionFromExtras(aFileExt, *_retval);
LOG(("Searched extras (by ext), rv 0x%08X\n", rv));
}
}
@ -2987,7 +3071,8 @@ NS_IMETHODIMP nsExternalHelperAppService::GetTypeFromFile(nsIFile* aFile, nsACSt
return GetTypeFromExtension(fileExt, aContentType);
}
nsresult nsExternalHelperAppService::GetMIMEInfoForMimeTypeFromExtras(const nsACString& aContentType, nsIMIMEInfo * aMIMEInfo )
nsresult nsExternalHelperAppService::FillMIMEInfoForMimeTypeFromExtras(
const nsACString& aContentType, nsIMIMEInfo * aMIMEInfo)
{
NS_ENSURE_ARG( aMIMEInfo );
@ -3014,13 +3099,14 @@ nsresult nsExternalHelperAppService::GetMIMEInfoForMimeTypeFromExtras(const nsAC
return NS_ERROR_NOT_AVAILABLE;
}
nsresult nsExternalHelperAppService::GetMIMEInfoForExtensionFromExtras(const nsACString& aExtension, nsIMIMEInfo * aMIMEInfo)
nsresult nsExternalHelperAppService::FillMIMEInfoForExtensionFromExtras(
const nsACString& aExtension, nsIMIMEInfo * aMIMEInfo)
{
nsCAutoString type;
PRBool found = GetTypeFromExtras(aExtension, type);
if (!found)
return NS_ERROR_NOT_AVAILABLE;
return GetMIMEInfoForMimeTypeFromExtras(type, aMIMEInfo);
return FillMIMEInfoForMimeTypeFromExtras(type, aMIMEInfo);
}
PRBool nsExternalHelperAppService::GetTypeFromExtras(const nsACString& aExtension, nsACString& aMIMEType)

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

@ -121,14 +121,40 @@ public:
NS_HIDDEN_(nsresult) Init();
/**
* Given a content type, look up the user override information to see if
* we have a mime info object representing this content type. The user
* over ride information is contained in a in memory data source.
* Given an existing MIME info object and a MIME type, fill in any user
* override info from the in-memory data source.
*
* @param aContentType The MIME content-type
* @param aMIMEInfo The mime info to fill with the information
*/
NS_HIDDEN_(nsresult) FillMIMEInfoForMimeTypeFromDS(
const nsACString& aContentType, nsIMIMEInfo * aMIMEInfo);
/**
* Given an existing protocol info object and a protocol scheme, fill in
* any user override info from the in-memory data source.
*
* @param aScheme The protocol scheme
* @param aMIMEInfo The mime info to fill with the information
*/
NS_HIDDEN_(nsresult) GetMIMEInfoForMimeTypeFromDS(const nsACString& aContentType,
nsIMIMEInfo * aMIMEInfo);
NS_HIDDEN_(nsresult) FillProtoInfoForSchemeFromDS(
const nsACString& aScheme, nsIHandlerInfo * aMIMEInfo);
/**
* Fill in the generic handler info stuff; called by Fill*InfoFor*FromDS.
*
* @param aTypeNodeResource RDF resource representing the top level scheme
* or MIME-type node in the graph
* @param aType content-type or scheme name
* @param aRDFService the RDF service
* @param aTypeNodePrefix One of NC_{CONTENT,SCHEME}_NODE_PREFIX
* @param aHandlerInfo object to be filled in
*/
NS_HIDDEN_(nsresult) FillHandlerInfoForTypeFromDS(
nsIRDFResource *aTypeNodeResource, const nsCAutoString& aType,
nsIRDFService *aRDFService, const char *aTypeNodePrefix,
nsIHandlerInfo * aHandlerInfo);
/**
* Given an extension, look up the user override information to see if we
* have a mime info object representing this extension. The user over ride
@ -138,8 +164,8 @@ public:
*
* @param aMIMEInfo The mime info to fill with the information
*/
NS_HIDDEN_(nsresult) GetMIMEInfoForExtensionFromDS(const nsACString& aFileExtension,
nsIMIMEInfo * aMIMEInfo);
NS_HIDDEN_(nsresult) FillMIMEInfoForExtensionFromDS(
const nsACString& aFileExtension, nsIMIMEInfo * aMIMEInfo);
/**
* Looks up the MIME Type for a given extension in the RDF Datasource.
@ -196,8 +222,8 @@ public:
* Return the URI template for any configured web handler. This will
* probably be replaced by something on nsIWebContentConverterService soon.
*/
static NS_HIDDEN_(nsresult) GetWebProtocolHandlerURITemplate(const nsACString &aScheme,
nsACString &aUriTemplate);
NS_HIDDEN_(nsresult) GetProtocolHandlerInfo(const nsACString &aScheme,
nsIHandlerInfo **aHandlerInfo);
virtual NS_HIDDEN_(nsresult) OSProtocolHandlerExists(const char *aScheme,
PRBool *aExists) = 0;
@ -219,6 +245,7 @@ protected:
nsCOMPtr<nsIRDFResource> kNC_AlwaysAsk;
nsCOMPtr<nsIRDFResource> kNC_HandleInternal;
nsCOMPtr<nsIRDFResource> kNC_PrettyName;
nsCOMPtr<nsIRDFResource> kNC_UriTemplate;
#endif
/**
@ -232,16 +259,17 @@ protected:
* The content type of the MIME Info will not be changed.
*/
#ifdef MOZ_RDF
NS_HIDDEN_(nsresult) FillTopLevelProperties(nsIRDFResource * aContentTypeNodeResource,
nsIRDFService * aRDFService,
nsIMIMEInfo * aMIMEInfo);
NS_HIDDEN_(nsresult) FillMIMEExtensionProperties(
nsIRDFResource * aContentTypeNodeResource, nsIRDFService * aRDFService,
nsIMIMEInfo * aMIMEInfo);
/**
* @see FillTopLevelProperties
* @see FillMIMEExtensionProperties
*/
NS_HIDDEN_(nsresult) FillContentHandlerProperties(const char * aContentType,
nsIRDFResource * aContentTypeNodeResource,
const char * aNodePrefix,
nsIRDFService * aRDFService,
nsIMIMEInfo * aMIMEInfo);
nsIHandlerInfo * aHandler);
/**
* A small helper function which gets the target for a given source and
@ -261,18 +289,18 @@ protected:
* @param aContentType The type to search for.
* @param aMIMEInfo [inout] The mime info, if found
*/
NS_HIDDEN_(nsresult) GetMIMEInfoForMimeTypeFromExtras(const nsACString& aContentType,
nsIMIMEInfo * aMIMEInfo);
NS_HIDDEN_(nsresult) FillMIMEInfoForMimeTypeFromExtras(
const nsACString& aContentType, nsIMIMEInfo * aMIMEInfo);
/**
* Searches the "extra" array of MIMEInfo objects for an object
* with a specific extension.
*
* Does not change the MIME Type of the MIME Info.
*
* @see GetMIMEInfoForMimeTypeFromExtras
* @see FillMIMEInfoForMimeTypeFromExtras
*/
NS_HIDDEN_(nsresult) GetMIMEInfoForExtensionFromExtras(const nsACString& aExtension,
nsIMIMEInfo * aMIMEInfo);
NS_HIDDEN_(nsresult) FillMIMEInfoForExtensionFromExtras(
const nsACString& aExtension, nsIMIMEInfo * aMIMEInfo);
/**
* Searches the "extra" array for a MIME type, and gets its extension.

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

@ -69,7 +69,7 @@
class nsExtProtocolChannel : public nsIChannel
{
friend class nsWebProtocolRedirect;
friend class nsProtocolRedirect;
public:
NS_DECL_ISUPPORTS
@ -83,14 +83,19 @@ public:
private:
nsresult OpenURL();
void Finish(nsresult aResult);
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIURI> mOriginalURI;
nsresult mStatus;
nsLoadFlags mLoadFlags;
PRBool mIsPending;
PRBool mWasOpened;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mContext;
};
NS_IMPL_THREADSAFE_ADDREF(nsExtProtocolChannel)
@ -102,7 +107,9 @@ NS_INTERFACE_MAP_BEGIN(nsExtProtocolChannel)
NS_INTERFACE_MAP_ENTRY(nsIRequest)
NS_INTERFACE_MAP_END_THREADSAFE
nsExtProtocolChannel::nsExtProtocolChannel() : mStatus(NS_OK)
nsExtProtocolChannel::nsExtProtocolChannel() : mStatus(NS_OK),
mIsPending(PR_FALSE),
mWasOpened(PR_FALSE)
{
}
@ -199,21 +206,44 @@ NS_IMETHODIMP nsExtProtocolChannel::Open(nsIInputStream **_retval)
return NS_ERROR_NO_CONTENT; // force caller to abort.
}
class nsWebProtocolRedirect : public nsRunnable {
class nsProtocolRedirect : public nsRunnable {
public:
nsWebProtocolRedirect(nsIURI *aURI, const nsACString & aUriTemplate,
nsIStreamListener *aListener, nsISupports *aContext,
nsExtProtocolChannel *aOriginalChannel)
: mURI(aURI), mUriTemplate(aUriTemplate), mListener(aListener),
nsProtocolRedirect(nsIURI *aURI, nsIHandlerInfo *aHandlerInfo,
nsIStreamListener *aListener, nsISupports *aContext,
nsExtProtocolChannel *aOriginalChannel)
: mURI(aURI), mHandlerInfo(aHandlerInfo), mListener(aListener),
mContext(aContext), mOriginalChannel(aOriginalChannel) {}
NS_IMETHOD Run()
{
// for now, this code path is only take for a web-based protocol handler
nsCOMPtr<nsIHandlerApp> handlerApp;
nsresult rv =
mHandlerInfo->GetPreferredApplicationHandler(getter_AddRefs(handlerApp));
if (NS_FAILED(rv)) {
mOriginalChannel->Finish(rv);
return NS_OK;
}
nsCOMPtr<nsIWebHandlerApp> webHandlerApp = do_QueryInterface(handlerApp,
&rv);
if (NS_FAILED(rv)) {
mOriginalChannel->Finish(rv);
return NS_OK;
}
nsCAutoString uriTemplate;
rv = webHandlerApp->GetUriTemplate(uriTemplate);
if (NS_FAILED(rv)) {
mOriginalChannel->Finish(rv);
return NS_OK;
}
// get the URI spec so we can escape it for insertion into the template
nsCAutoString uriSpecToHandle;
nsresult rv = mURI->GetSpec(uriSpecToHandle);
rv = mURI->GetSpec(uriSpecToHandle);
if (NS_FAILED(rv)) {
AbandonOriginalChannel(rv);
mOriginalChannel->Finish(rv);
return NS_OK;
}
@ -235,15 +265,15 @@ class nsWebProtocolRedirect : public nsRunnable {
// handled. The HTML5 draft doesn't prohibit %s from occurring more than
// once, and if it does, I can't think of any problems that could
// cause, (though I don't know why anyone would need or want to do it).
mUriTemplate.ReplaceSubstring(NS_LITERAL_CSTRING("%s"),
escapedUriSpecToHandle);
uriTemplate.ReplaceSubstring(NS_LITERAL_CSTRING("%s"),
escapedUriSpecToHandle);
// convert spec to URI; no original charset needed since there's no way
// to communicate that information to any handler
nsCOMPtr<nsIURI> uriToSend;
rv = NS_NewURI(getter_AddRefs(uriToSend), mUriTemplate);
rv = NS_NewURI(getter_AddRefs(uriToSend), uriTemplate);
if (NS_FAILED(rv)) {
AbandonOriginalChannel(rv);
mOriginalChannel->Finish(rv);
return NS_OK;
}
@ -252,9 +282,10 @@ class nsWebProtocolRedirect : public nsRunnable {
rv = NS_NewChannel(getter_AddRefs(newChannel), uriToSend, nsnull,
mOriginalChannel->mLoadGroup,
mOriginalChannel->mCallbacks,
mOriginalChannel->mLoadFlags);
mOriginalChannel->mLoadFlags
| nsIChannel::LOAD_REPLACE);
if (NS_FAILED(rv)) {
AbandonOriginalChannel(rv);
mOriginalChannel->Finish(rv);
return NS_OK;
}
@ -268,76 +299,115 @@ class nsWebProtocolRedirect : public nsRunnable {
nsIChannelEventSink::REDIRECT_TEMPORARY |
nsIChannelEventSink::REDIRECT_INTERNAL);
if (NS_FAILED(rv)) {
AbandonOriginalChannel(rv);
mOriginalChannel->Finish(rv);
return NS_OK;
}
}
rv = newChannel->AsyncOpen(mListener, mContext);
if (NS_FAILED(rv)) {
AbandonOriginalChannel(rv);
mOriginalChannel->Finish(rv);
return NS_OK;
}
mOriginalChannel->mStatus = NS_BINDING_REDIRECTED;
mOriginalChannel->Finish(NS_BINDING_REDIRECTED);
return NS_OK;
}
private:
nsCOMPtr<nsIURI> mURI;
nsCString mUriTemplate;
nsCOMPtr<nsIHandlerInfo> mHandlerInfo;
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsExtProtocolChannel> mOriginalChannel;
// necko guarantees that after an AsyncOpen has succeeded, OnStartRequest
// and OnStopRequest will get called
void AbandonOriginalChannel(const nsresult aStatus)
{
mOriginalChannel->mStatus = aStatus;
(void)mListener->OnStartRequest(mOriginalChannel, mContext);
(void)mListener->OnStopRequest(mOriginalChannel, mContext, aStatus);
return;
}
};
NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
{
// check whether the scheme is one that we have a web handler for
nsCAutoString urlScheme;
nsresult rv = mUrl->GetScheme(urlScheme);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIExternalProtocolService> extProtService =
do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString uriTemplate;
rv = nsExternalHelperAppService::GetWebProtocolHandlerURITemplate(urlScheme,
uriTemplate);
if (NS_SUCCEEDED(rv)) {
NS_ENSURE_ARG_POINTER(listener);
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
// redirecting to the web handler involvegs calling OnChannelRedirect,
// which is supposed to happen after AsyncOpen completes, so we do it in an
// event
nsCOMPtr<nsIRunnable> event = new nsWebProtocolRedirect(mUrl, uriTemplate,
listener, ctxt,
this);
// We don't check if |event| was successfully created because
// |NS_DispatchToCurrentThread| will do that for us.
rv = NS_DispatchToCurrentThread(event);
if (NS_SUCCEEDED(rv)) {
return rv;
}
mWasOpened = PR_TRUE;
mListener = listener;
mContext = ctxt;
if (!gExtProtSvc) {
return NS_ERROR_FAILURE;
}
// try for an OS-provided handler
nsCAutoString urlScheme;
nsresult rv = mUrl->GetScheme(urlScheme);
if (NS_FAILED(rv)) {
return rv;
}
// check whether the scheme is one that we have a web handler for
nsCOMPtr<nsIHandlerInfo> handlerInfo;
rv = gExtProtSvc->GetProtocolHandlerInfo(urlScheme,
getter_AddRefs(handlerInfo));
if (NS_SUCCEEDED(rv)) {
PRInt32 preferredAction;
rv = handlerInfo->GetPreferredAction(&preferredAction);
// for now, anything that triggers a helper app is going to be a web-based
// protocol handler, so we use that to decide which path to take...
if (preferredAction == nsIHandlerInfo::useHelperApp) {
// redirecting to the web handler involves calling OnChannelRedirect
// (which is supposed to happen after AsyncOpen completes) or possibly
// opening a dialog, so we do it in an event
nsCOMPtr<nsIRunnable> event = new nsProtocolRedirect(mUrl, handlerInfo,
listener, ctxt,
this);
// We don't check if |event| was successfully created because
// |NS_DispatchToCurrentThread| will do that for us.
rv = NS_DispatchToCurrentThread(event);
if (NS_SUCCEEDED(rv)) {
mIsPending = PR_TRUE;
// add ourselves to the load group, since this isn't going to finish
// immediately
if (mLoadGroup)
(void)mLoadGroup->AddRequest(this, nsnull);
return rv;
}
}
}
// no protocol info found, just fall back on whatever the OS has to offer
OpenURL();
return NS_ERROR_NO_CONTENT; // force caller to abort.
}
/**
* Finish out what was started in AsyncOpen. This can be called in either the
* success or the failure case.
*
* @param aStatus used to set the channel's status, and, if this set to
* anything other than NS_BINDING_REDIRECTED, OnStartRequest
* and OnStopRequest will be called, since Necko guarantees
* this will happen unless the redirect took place.
*/
void nsExtProtocolChannel::Finish(nsresult aStatus)
{
mStatus = aStatus;
if (aStatus != NS_BINDING_REDIRECTED && mListener) {
(void)mListener->OnStartRequest(this, mContext);
(void)mListener->OnStopRequest(this, mContext, aStatus);
}
mIsPending = PR_FALSE;
if (mLoadGroup) {
(void)mLoadGroup->RemoveRequest(this, nsnull, aStatus);
}
return;
}
NS_IMETHODIMP nsExtProtocolChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
{
*aLoadFlags = mLoadFlags;
@ -406,7 +476,7 @@ NS_IMETHODIMP nsExtProtocolChannel::GetName(nsACString &result)
NS_IMETHODIMP nsExtProtocolChannel::IsPending(PRBool *result)
{
*result = PR_TRUE;
*result = mIsPending;
return NS_OK;
}

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

@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim:expandtab:shiftwidth=2:tabstop=2:cin:
* ***** 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 the Mozilla browser.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Mosedale <dmose@mozilla.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
#include "nsHandlerAppImpl.h"
// XXX why does nsMIMEInfoImpl have a threadsafe nsISupports? do we need one
// here too?
NS_IMPL_ISUPPORTS1(nsHandlerAppBase, nsIHandlerApp)
/* AString name; */
NS_IMETHODIMP nsHandlerAppBase::GetName(nsAString & aName)
{
aName.Assign(mName);
return NS_OK;
}
NS_IMETHODIMP nsHandlerAppBase::SetName(const nsAString & aName)
{
mName.Assign(aName);
return NS_OK;
}
NS_IMPL_ISUPPORTS_INHERITED1(nsLocalHandlerApp, nsHandlerAppBase, nsILocalHandlerApp)
NS_IMETHODIMP nsLocalHandlerApp::GetName(nsAString& aName)
{
if (mName.IsEmpty() && mExecutable) {
// Don't want to cache this, just in case someone resets the app
// without changing the description....
mExecutable->GetLeafName(aName);
} else {
aName.Assign(mName);
}
return NS_OK;
}
NS_IMETHODIMP nsLocalHandlerApp::GetExecutable(nsIFile **aExecutable)
{
NS_IF_ADDREF(*aExecutable = mExecutable);
return NS_OK;
}
NS_IMETHODIMP nsLocalHandlerApp::SetExecutable(nsIFile *aExecutable)
{
mExecutable = aExecutable;
return NS_OK;
}
NS_IMPL_ISUPPORTS_INHERITED1(nsWebHandlerApp, nsHandlerAppBase,
nsIWebHandlerApp)
NS_IMETHODIMP nsWebHandlerApp::GetUriTemplate(nsACString &aUriTemplate)
{
aUriTemplate.Assign(mUriTemplate);
return NS_OK;
}
NS_IMETHODIMP nsWebHandlerApp::SetUriTemplate(const nsACString &aUriTemplate)
{
mUriTemplate.Assign(aUriTemplate);
return NS_OK;
}

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

@ -0,0 +1,102 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim:expandtab:shiftwidth=2:tabstop=2:cin:
* ***** 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 the Mozilla browser.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Mosedale <dmose@mozilla.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
#ifndef __nshandlerappimpl_h__
#define __nshandlerappimpl_h__
#include "nsString.h"
#include "nsIMIMEInfo.h"
#include "nsIFile.h"
class nsHandlerAppBase : public nsIHandlerApp
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIHANDLERAPP
nsHandlerAppBase() NS_HIDDEN {}
nsHandlerAppBase(const PRUnichar *aName) NS_HIDDEN { mName.Assign(aName); };
nsHandlerAppBase(const nsAString & aName) NS_HIDDEN { mName.Assign(aName); };
virtual ~nsHandlerAppBase() {};
protected:
nsString mName;
};
class nsLocalHandlerApp : public nsHandlerAppBase, public nsILocalHandlerApp
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSILOCALHANDLERAPP
nsLocalHandlerApp() {};
nsLocalHandlerApp(const PRUnichar *aName, nsIFile *aExecutable)
: nsHandlerAppBase(aName), mExecutable(aExecutable) {}
nsLocalHandlerApp(const nsAString & aName, nsIFile *aExecutable)
: nsHandlerAppBase(aName), mExecutable(aExecutable) {}
virtual ~nsLocalHandlerApp() {};
// overriding to keep old caching behavior (that a useful name is returned
// even if none was given to the constructor)
NS_IMETHOD GetName(nsAString & aName);
protected:
nsCOMPtr<nsIFile> mExecutable;
};
class nsWebHandlerApp : public nsHandlerAppBase, public nsIWebHandlerApp
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIWEBHANDLERAPP
nsWebHandlerApp(const PRUnichar *aName, const nsACString &aUriTemplate)
: nsHandlerAppBase(aName), mUriTemplate(aUriTemplate) { }
virtual ~nsWebHandlerApp() {};
protected:
nsCString mUriTemplate;
};
#endif // __nshandlerappimpl_h__

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

@ -57,8 +57,12 @@
#define NC_RDF_CHILD NC_NAMESPACE_URI"child"
#define NC_RDF_ROOT "NC:HelperAppRoot"
#define NC_CONTENT_NODE_PREFIX "urn:mimetype:"
#define NC_CONTENT_NODE_HANDLER_PREFIX "urn:mimetype:handler:"
#define NC_CONTENT_NODE_EXTERNALAPP_PREFIX "urn:mimetype:externalApplication:"
#define NC_HANDLER_SUFFIX "handler:"
#define NC_EXTERNALAPP_SUFFIX "externalApplication:"
// for URI schemes. We re-use NC_RDF_HANDLER as an arc from these nodes.
#define NC_SCHEME_NODE_PREFIX "urn:scheme:"
#define NS_RDF_PROTOCOLSCHEMES NC_NAMESPACE_URI"Protocol-Schemes"
// File Extensions have file extension properties....
#define NC_RDF_FILEEXTENSION NC_NAMESPACE_URI"fileExtension"
@ -72,5 +76,7 @@
// external applications properties....
#define NC_RDF_PRETTYNAME NC_NAMESPACE_URI"prettyName"
// for local apps, we'll have the path (but not uriTemplate)
#define NC_RDF_PATH NC_NAMESPACE_URI"path"
// for web apps, we'll have the uriTemplate (but not path)
#define NC_RDF_URITEMPLATE NC_NAMESPACE_URI"uriTemplate"

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

@ -43,7 +43,7 @@
#include "nsIProcess.h"
// nsISupports methods
NS_IMPL_THREADSAFE_ISUPPORTS1(nsMIMEInfoBase, nsIMIMEInfo)
NS_IMPL_THREADSAFE_ISUPPORTS2(nsMIMEInfoBase, nsIMIMEInfo, nsIHandlerInfo)
// nsMIMEInfoImpl methods
nsMIMEInfoBase::nsMIMEInfoBase(const char *aMIMEType) :
@ -225,27 +225,6 @@ nsMIMEInfoBase::SetFileExtensions(const nsACString& aExtensions)
return NS_OK;
}
NS_IMETHODIMP
nsMIMEInfoBase::GetApplicationDescription(nsAString& aApplicationDescription)
{
if (mPreferredAppDescription.IsEmpty() && mPreferredApplication) {
// Don't want to cache this, just in case someone resets the app
// without changing the description....
mPreferredApplication->GetLeafName(aApplicationDescription);
} else {
aApplicationDescription = mPreferredAppDescription;
}
return NS_OK;
}
NS_IMETHODIMP
nsMIMEInfoBase::SetApplicationDescription(const nsAString& aApplicationDescription)
{
mPreferredAppDescription = aApplicationDescription;
return NS_OK;
}
NS_IMETHODIMP
nsMIMEInfoBase::GetDefaultDescription(nsAString& aDefaultDescription)
{
@ -254,7 +233,7 @@ nsMIMEInfoBase::GetDefaultDescription(nsAString& aDefaultDescription)
}
NS_IMETHODIMP
nsMIMEInfoBase::GetPreferredApplicationHandler(nsIFile ** aPreferredAppHandler)
nsMIMEInfoBase::GetPreferredApplicationHandler(nsIHandlerApp ** aPreferredAppHandler)
{
*aPreferredAppHandler = mPreferredApplication;
NS_IF_ADDREF(*aPreferredAppHandler);
@ -262,21 +241,21 @@ nsMIMEInfoBase::GetPreferredApplicationHandler(nsIFile ** aPreferredAppHandler)
}
NS_IMETHODIMP
nsMIMEInfoBase::SetPreferredApplicationHandler(nsIFile * aPreferredAppHandler)
nsMIMEInfoBase::SetPreferredApplicationHandler(nsIHandlerApp * aPreferredAppHandler)
{
mPreferredApplication = aPreferredAppHandler;
return NS_OK;
}
NS_IMETHODIMP
nsMIMEInfoBase::GetPreferredAction(nsMIMEInfoHandleAction * aPreferredAction)
nsMIMEInfoBase::GetPreferredAction(nsHandlerInfoAction * aPreferredAction)
{
*aPreferredAction = mPreferredAction;
return NS_OK;
}
NS_IMETHODIMP
nsMIMEInfoBase::SetPreferredAction(nsMIMEInfoHandleAction aPreferredAction)
nsMIMEInfoBase::SetPreferredAction(nsHandlerInfoAction aPreferredAction)
{
mPreferredAction = aPreferredAction;
return NS_OK;
@ -304,7 +283,16 @@ nsMIMEInfoBase::LaunchWithFile(nsIFile* aFile)
if (!mPreferredApplication)
return NS_ERROR_FILE_NOT_FOUND;
return LaunchWithIProcess(mPreferredApplication, aFile);
nsCOMPtr<nsILocalHandlerApp> localHandler;
nsresult rv;
localHandler = do_QueryInterface(mPreferredApplication, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> executable;
rv = localHandler->GetExecutable(getter_AddRefs(executable));
NS_ENSURE_SUCCESS(rv, rv);
return LaunchWithIProcess(executable, aFile);
}
else if (mPreferredAction == useSystemDefault) {
return LaunchDefaultWithFile(aFile);

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

@ -21,6 +21,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Mosedale <dmose@mozilla.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -81,14 +82,12 @@ class nsMIMEInfoBase : public nsIMIMEInfo {
NS_IMETHOD GetMacCreator(PRUint32 *aMacCreator);
NS_IMETHOD SetMacCreator(PRUint32 aMacCreator);
NS_IMETHOD Equals(nsIMIMEInfo *aMIMEInfo, PRBool *_retval);
NS_IMETHOD GetPreferredApplicationHandler(nsIFile * *aPreferredApplicationHandler);
NS_IMETHOD SetPreferredApplicationHandler(nsIFile * aPreferredApplicationHandler);
NS_IMETHOD GetApplicationDescription(nsAString & aApplicationDescription);
NS_IMETHOD SetApplicationDescription(const nsAString & aApplicationDescription);
NS_IMETHOD GetPreferredApplicationHandler(nsIHandlerApp * *aPreferredApplicationHandler);
NS_IMETHOD SetPreferredApplicationHandler(nsIHandlerApp * aPreferredApplicationHandler);
NS_IMETHOD GetDefaultDescription(nsAString & aDefaultDescription);
NS_IMETHOD LaunchWithFile(nsIFile *aFile);
NS_IMETHOD GetPreferredAction(nsMIMEInfoHandleAction *aPreferredAction);
NS_IMETHOD SetPreferredAction(nsMIMEInfoHandleAction aPreferredAction);
NS_IMETHOD GetPreferredAction(nsHandlerInfoAction *aPreferredAction);
NS_IMETHOD SetPreferredAction(nsHandlerInfoAction aPreferredAction);
NS_IMETHOD GetAlwaysAskBeforeHandling(PRBool *aAlwaysAskBeforeHandling);
NS_IMETHOD SetAlwaysAskBeforeHandling(PRBool aAlwaysAskBeforeHandling);
@ -143,8 +142,8 @@ class nsMIMEInfoBase : public nsIMIMEInfo {
nsString mDescription; ///< human readable description
PRUint32 mMacType, mMacCreator; ///< Mac file type and creator
nsCString mMIMEType;
nsCOMPtr<nsIFile> mPreferredApplication; ///< preferred application associated with this type.
nsMIMEInfoHandleAction mPreferredAction; ///< preferred action to associate with this type
nsCOMPtr<nsIHandlerApp> mPreferredApplication;
nsHandlerInfoAction mPreferredAction; ///< preferred action to associate with this type
nsString mPreferredAppDescription;
nsString mDefaultAppDescription;
PRBool mAlwaysAskBeforeHandling;

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

@ -111,11 +111,24 @@ static nsresult GetIconURLVariant(nsIFile* aApplication, nsIVariant* *_retval)
NS_IMETHODIMP
nsMIMEInfoWin::GetProperty(const nsAString& aName, nsIVariant* *_retval)
{
nsresult rv = NS_ERROR_FAILURE;
if (mDefaultApplication && aName.EqualsLiteral(PROPERTY_DEFAULT_APP_ICON_URL))
nsresult rv;
if (mDefaultApplication && aName.EqualsLiteral(PROPERTY_DEFAULT_APP_ICON_URL)) {
rv = GetIconURLVariant(mDefaultApplication, _retval);
else if (mPreferredApplication && aName.EqualsLiteral(PROPERTY_CUSTOM_APP_ICON_URL))
rv = GetIconURLVariant(mPreferredApplication, _retval);
return rv;
NS_ENSURE_SUCCESS(rv, rv);
} else if (mPreferredApplication &&
aName.EqualsLiteral(PROPERTY_CUSTOM_APP_ICON_URL)) {
nsCOMPtr<nsILocalHandlerApp> localHandler =
do_QueryInterface(mPreferredApplication, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> executable;
rv = localHandler->GetExecutable(getter_AddRefs(executable));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetIconURLVariant(executable, _retval);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}