зеркало из https://github.com/mozilla/gecko-dev.git
Refactor nsIMIMEInfo and nsExternalHelperAppService to support local and web-based protocol handlers (bug 384374), r=biesi, sr=sicking
This commit is contained in:
Родитель
10dbfc6ede
Коммит
ec036ba262
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче