bug 388388: differentiate between MIME and protocol nsIHandlerInfo objects by not allowing protocol objects to be QIed to nsIMIMEInfo, and expose the scheme for a protocol object via the new nsIHandlerInfo::type attribute (which also holds the MIME type for a MIME object and deprecates nsIMIMEInfo::MIMEType); r=dmose, sr=biesi
authormyk@mozilla.org
Tue, 24 Jul 2007 13:29:50 -0700
changeset 3852 94b8340e78582f23a4bb4090583233d8aa665bba
parent 3851 e65b09809a014174e5632750241a1f000c9e6307
child 3853 ecdaa6d51ed15fe3adf6e510cc408f964075fceb
push idunknown
push userunknown
push dateunknown
reviewersdmose, biesi
bugs388388
milestone1.9a7pre
bug 388388: differentiate between MIME and protocol nsIHandlerInfo objects by not allowing protocol objects to be QIed to nsIMIMEInfo, and expose the scheme for a protocol object via the new nsIHandlerInfo::type attribute (which also holds the MIME type for a MIME object and deprecates nsIMIMEInfo::MIMEType); r=dmose, sr=biesi
netwerk/mime/public/nsIMIMEInfo.idl
uriloader/exthandler/beos/nsMIMEInfoBeOS.h
uriloader/exthandler/beos/nsOSHelperAppService.cpp
uriloader/exthandler/mac/nsMIMEInfoMac.h
uriloader/exthandler/mac/nsOSHelperAppService.cpp
uriloader/exthandler/nsHandlerService.js
uriloader/exthandler/nsMIMEInfoImpl.cpp
uriloader/exthandler/nsMIMEInfoImpl.h
uriloader/exthandler/os2/nsMIMEInfoOS2.h
uriloader/exthandler/tests/unit/test_handlerService.js
uriloader/exthandler/unix/nsOSHelperAppService.cpp
uriloader/exthandler/win/nsMIMEInfoWin.h
uriloader/exthandler/win/nsOSHelperAppService.cpp
--- a/netwerk/mime/public/nsIMIMEInfo.idl
+++ b/netwerk/mime/public/nsIMIMEInfo.idl
@@ -44,19 +44,27 @@ interface nsIUTF8StringEnumerator;
 interface nsIHandlerApp;
 
 typedef long nsHandlerInfoAction;
 
 /**
  * nsIHandlerInfo gives access to the information about how a given protocol
  * scheme or MIME-type is handled.
  */
-[scriptable, uuid(2ec1216d-59e7-424c-aa1e-70aa3c897520)]
+[scriptable, uuid(51ddc1c5-7077-4c58-a5bd-327d00777b46)]
 interface nsIHandlerInfo : nsISupports {
     /**
+     * The type of this handler info.  For MIME handlers, this is the MIME type.
+     * For protocol handlers, it's the scheme.
+     * 
+     * @return String representing the type.
+     */
+    readonly attribute ACString type;
+
+    /**
      * 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!!
      */
@@ -153,16 +161,18 @@ interface nsIMIMEInfo : nsIHandlerInfo {
      * @return The first extension.
      */
     attribute AUTF8String primaryExtension;
     
     /**
      * The MIME type of this MIMEInfo.
      * 
      * @return String representing the MIME type.
+     * 
+     * @deprecated  use nsIHandlerInfo::type instead.
      */
     readonly attribute ACString MIMEType;
 
     /**
      * Mac Type and creator types
      */
     attribute PRUint32 macType;
     attribute PRUint32 macCreator;
--- a/uriloader/exthandler/beos/nsMIMEInfoBeOS.h
+++ b/uriloader/exthandler/beos/nsMIMEInfoBeOS.h
@@ -38,15 +38,17 @@
 #define nsMIMEInfoBeOS_h_
 
 #include "nsMIMEInfoImpl.h"
 
 class nsMIMEInfoBeOS : public nsMIMEInfoImpl {
   public:
     nsMIMEInfoBeOS(const char* aType = "") : nsMIMEInfoImpl(aType) {}
     nsMIMEInfoBeOS(const nsACString& aMIMEType) : nsMIMEInfoImpl(aMIMEType) {}
+    nsMIMEInfoBeOS(const nsACString& aType, HandlerClass aClass) :
+      nsMIMEInfoImpl(aType, aClass) {}
     virtual ~nsMIMEInfoBeOS();
 
   protected:
     virtual NS_HIDDEN_(nsresult) LaunchDefaultWithFile(nsIFile* aFile);
 };
 
 #endif
--- a/uriloader/exthandler/beos/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/beos/nsOSHelperAppService.cpp
@@ -270,17 +270,18 @@ nsOSHelperAppService::GetProtocolInfoFro
 {
   NS_ASSERTION(!aScheme.IsEmpty(), "No scheme was specified!");
 
   PRBool exists;
   nsresult rv = OSProtocolHandlerExists(nsPromiseFlatCString(aScheme).get(),
                                         &exists);
   NS_ENSURE_SUCCESS(rv, nsnull);
 
-  nsMIMEInfoBeOS *handlerInfo = new nsMIMEInfoBeOS();
+  nsMIMEInfoBeOS *handlerInfo =
+	new nsMIMEInfoBeOS(aScheme, nsMIMEInfoBase::eProtocolInfo);
   NS_ENSURE_TRUE(handlerInfo, nsnull);
   NS_ADDREF(handlerInfo);
 
   nsAutoString desc;
   GetApplicationDescription(aScheme, desc);
   handlerInfo->SetDefaultDescription(desc);
 
   return handlerInfo;
--- a/uriloader/exthandler/mac/nsMIMEInfoMac.h
+++ b/uriloader/exthandler/mac/nsMIMEInfoMac.h
@@ -38,16 +38,18 @@
 #define nsMIMEInfoMac_h_
 
 #include "nsMIMEInfoImpl.h"
 
 class nsMIMEInfoMac : public nsMIMEInfoImpl {
   public:
     nsMIMEInfoMac(const char* aMIMEType = "") : nsMIMEInfoImpl(aMIMEType) {}
     nsMIMEInfoMac(const nsACString& aMIMEType) : nsMIMEInfoImpl(aMIMEType) {}
+    nsMIMEInfoMac(const nsACString& aType, HandlerClass aClass) :
+      nsMIMEInfoImpl(aType, aClass) {}
 
     NS_IMETHOD LaunchWithURI(nsIURI* aURI);
 
 #ifdef DEBUG
   protected:
     virtual NS_HIDDEN_(nsresult) LaunchDefaultWithFile(nsIFile* aFile) {
       NS_NOTREACHED("do not call this method, use LaunchWithFile");
       return NS_ERROR_UNEXPECTED;
--- a/uriloader/exthandler/mac/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/mac/nsOSHelperAppService.cpp
@@ -338,17 +338,18 @@ nsOSHelperAppService::GetProtocolInfoFro
 {
   NS_ASSERTION(!aScheme.IsEmpty(), "No scheme was specified!");
 
   PRBool exists;
   nsresult rv = OSProtocolHandlerExists(nsPromiseFlatCString(aScheme).get(),
                                         &exists);
   NS_ENSURE_SUCCESS(rv, nsnull);
 
-  nsMIMEInfoMac *handlerInfo = new nsMIMEInfoMac();
+  nsMIMEInfoMac *handlerInfo =
+    new nsMIMEInfoMac(aScheme, nsMIMEInfoBase::eProtocolInfo);
   NS_ENSURE_TRUE(handlerInfo, nsnull);
   NS_ADDREF(handlerInfo);
 
   nsAutoString desc;
   GetApplicationDescription(aScheme, desc);
   handlerInfo->SetDefaultDescription(desc);
 
   return handlerInfo;
--- a/uriloader/exthandler/nsHandlerService.js
+++ b/uriloader/exthandler/nsHandlerService.js
@@ -239,19 +239,17 @@ HandlerService.prototype = {
    * Get the string identifying whether this is a MIME or a protocol handler.
    * This string is used in the URI IDs of various RDF properties.
    * 
    * @param aHandlerInfo {nsIHandlerInfo} the handler for which to get the class
    * 
    * @returns {string} the ID
    */
   _getClass: function HS__getClass(aHandlerInfo) {
-    if (aHandlerInfo instanceof Ci.nsIMIMEInfo &&
-        // FIXME: remove this extra condition in the fix for bug 388388.
-        aHandlerInfo.QueryInterface(Ci.nsIMIMEInfo).MIMEType)
+    if (aHandlerInfo instanceof Ci.nsIMIMEInfo)
       return "mimetype";
     else
       return "scheme";
   },
 
   /**
    * Return the unique identifier for a content type record, which stores
    * the editable and value fields plus a reference to the type's handler.
@@ -260,20 +258,17 @@ HandlerService.prototype = {
    * 
    * XXX: should this be a property of nsIHandlerInfo?
    * 
    * @param aHandlerInfo {nsIHandlerInfo} the type for which to get the ID
    * 
    * @returns {string} the ID
    */
   _getTypeID: function HS__getTypeID(aHandlerInfo) {
-    return "urn:" + this._getClass(aHandlerInfo) + ":" +
-           // FIXME: change this to aHandlerInfo.type in the fix for bug 388388.
-           aHandlerInfo.QueryInterface(Ci.nsIMIMEInfo).MIMEType;
-
+    return "urn:" + this._getClass(aHandlerInfo) + ":" + aHandlerInfo.type;
   },
 
   /**
    * Return the unique identifier for a type info record, which stores
    * the preferredAction and alwaysAsk fields plus a reference to the preferred
    * handler.  Roughly equivalent to the nsIHandlerInfo interface.
    * 
    * |urn:(mimetype|scheme):handler:<type>|
@@ -283,18 +278,17 @@ HandlerService.prototype = {
    * merely stores additional attributes of a content type.
    * 
    * @param aHandlerInfo {nsIHandlerInfo} the handler for which to get the ID
    * 
    * @returns {string} the ID
    */
   _getInfoID: function HS__getInfoID(aHandlerInfo) {
     return "urn:" + this._getClass(aHandlerInfo) + ":handler:" +
-           // FIXME: change this to aHandlerInfo.type in the fix for bug 388388.
-           aHandlerInfo.QueryInterface(Ci.nsIMIMEInfo).MIMEType;
+           aHandlerInfo.type;
   },
 
   /**
    * Return the unique identifier for a preferred handler record, which stores
    * information about the preferred handler for a given content type, including
    * its human-readable name and the path to its executable (for a local app)
    * or its URI template (for a web app).
    * 
@@ -309,18 +303,17 @@ HandlerService.prototype = {
    * the preferred one (once we support possible handlers).
    * 
    * @param aHandlerInfo {nsIHandlerInfo} the handler for which to get the ID
    * 
    * @returns {string} the ID
    */
   _getPreferredHandlerID: function HS__getPreferredHandlerID(aHandlerInfo) {
     return "urn:" + this._getClass(aHandlerInfo) + ":externalApplication:" +
-           // FIXME: change this to aHandlerInfo.type in the fix for bug 388388.
-           aHandlerInfo.QueryInterface(Ci.nsIMIMEInfo).MIMEType;
+           aHandlerInfo.type;
   },
 
   /**
    * Get the list of types for the given class, creating the list if it
    * doesn't already exist.  The class can be either "mimetype" or "scheme"
    * (i.e. the result of a call to _getClass).
    * 
    * |urn:(mimetype|scheme)s|
@@ -378,19 +371,17 @@ HandlerService.prototype = {
     var typeID = this._getTypeID(aHandlerInfo);
     var type = this._rdf.GetResource(typeID);
     if (typeList.IndexOf(type) != -1)
       return;
 
     // Create a basic type record for this type.
     typeList.AppendElement(type);
     this._setLiteral(typeID, NC_EDITABLE, "true");
-    this._setLiteral(typeID, NC_VALUE,
-        // FIXME: change this to aHandlerInfo.type in the fix for bug 388388.
-        aHandlerInfo.QueryInterface(Ci.nsIMIMEInfo).MIMEType);
+    this._setLiteral(typeID, NC_VALUE, aHandlerInfo.type);
     
     // Create a basic info record for this type.
     var infoID = this._getInfoID(aHandlerInfo);
     this._setLiteral(infoID, NC_ALWAYS_ASK, "false");
     this._setResource(typeID, NC_HANDLER_INFO, infoID);
     // XXX Shouldn't we set preferredAction to useSystemDefault?
     // That's what it is if there's no record in the datastore; why should it
     // change to useHelperApp just because we add a record to the datastore?
--- a/uriloader/exthandler/nsMIMEInfoImpl.cpp
+++ b/uriloader/exthandler/nsMIMEInfoImpl.cpp
@@ -40,37 +40,65 @@
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 #include "nsStringEnumerator.h"
 #include "nsIProcess.h"
 #include "nsILocalFile.h"
 #include "nsIFileURL.h"
 
 // nsISupports methods
-NS_IMPL_THREADSAFE_ISUPPORTS2(nsMIMEInfoBase, nsIMIMEInfo, nsIHandlerInfo)
+NS_IMPL_THREADSAFE_ADDREF(nsMIMEInfoBase)
+NS_IMPL_THREADSAFE_RELEASE(nsMIMEInfoBase)
+
+NS_INTERFACE_MAP_BEGIN(nsMIMEInfoBase)
+    NS_INTERFACE_MAP_ENTRY(nsIHandlerInfo)
+    // This is only an nsIMIMEInfo if it's a MIME handler with a MIME type.
+    NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMIMEInfo, !mMIMEType.IsEmpty())
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHandlerInfo)
+NS_INTERFACE_MAP_END_THREADSAFE
 
 // nsMIMEInfoImpl methods
+
+// Constructors for a MIME handler.
 nsMIMEInfoBase::nsMIMEInfoBase(const char *aMIMEType) :
     mMacType(0),
     mMacCreator(0),
+    mType(aMIMEType),
     mMIMEType(aMIMEType),
     mPreferredAction(nsIMIMEInfo::saveToDisk),
     mAlwaysAskBeforeHandling(PR_TRUE)
 {
 }
 
 nsMIMEInfoBase::nsMIMEInfoBase(const nsACString& aMIMEType) :
     mMacType(0),
     mMacCreator(0),
+    mType(aMIMEType),
     mMIMEType(aMIMEType),
     mPreferredAction(nsIMIMEInfo::saveToDisk),
     mAlwaysAskBeforeHandling(PR_TRUE)
 {
 }
 
+// Constructor for a handler that lets the caller specify whether this is a
+// MIME handler or a protocol handler.  In the long run, these will be distinct
+// classes (f.e. nsMIMEInfo and nsProtocolInfo), but for now we reuse this class
+// for both and distinguish between the two kinds of handlers via the aClass
+// argument to this method, which can be either eMIMEInfo or eProtocolInfo.
+nsMIMEInfoBase::nsMIMEInfoBase(const nsACString& aType, HandlerClass aClass) :
+    mMacType(0),
+    mMacCreator(0),
+    mType(aType),
+    mPreferredAction(nsIMIMEInfo::saveToDisk),
+    mAlwaysAskBeforeHandling(PR_TRUE)
+{
+  if (aClass == eMIMEInfo)
+    mMIMEType = aType;
+}
+
 nsMIMEInfoBase::~nsMIMEInfoBase()
 {
 }
 
 NS_IMETHODIMP
 nsMIMEInfoBase::GetFileExtensions(nsIUTF8StringEnumerator** aResult)
 {
   return NS_NewUTF8StringEnumerator(aResult, &mExtensions, this);
@@ -132,16 +160,26 @@ nsMIMEInfoBase::SetPrimaryExtension(cons
 NS_IMETHODIMP
 nsMIMEInfoBase::AppendExtension(const nsACString& aExtension)
 {
   mExtensions.AppendCString(aExtension);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsMIMEInfoBase::GetType(nsACString& aType)
+{
+    if (mType.IsEmpty())
+        return NS_ERROR_NOT_INITIALIZED;
+
+    aType = mType;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsMIMEInfoBase::GetMIMEType(nsACString& aMIMEType)
 {
     if (mMIMEType.IsEmpty())
         return NS_ERROR_NOT_INITIALIZED;
 
     aMIMEType = mMIMEType;
     return NS_OK;
 }
--- a/uriloader/exthandler/nsMIMEInfoImpl.h
+++ b/uriloader/exthandler/nsMIMEInfoImpl.h
@@ -69,16 +69,17 @@ class nsMIMEInfoBase : public nsIMIMEInf
 
     // I'd use NS_DECL_NSIMIMEINFO, but I don't want GetHasDefaultHandler
     NS_IMETHOD GetFileExtensions(nsIUTF8StringEnumerator **_retval);
     NS_IMETHOD SetFileExtensions(const nsACString & aExtensions);
     NS_IMETHOD ExtensionExists(const nsACString & aExtension, PRBool *_retval);
     NS_IMETHOD AppendExtension(const nsACString & aExtension);
     NS_IMETHOD GetPrimaryExtension(nsACString & aPrimaryExtension);
     NS_IMETHOD SetPrimaryExtension(const nsACString & aPrimaryExtension);
+    NS_IMETHOD GetType(nsACString & aType);
     NS_IMETHOD GetMIMEType(nsACString & aMIMEType);
     NS_IMETHOD GetDescription(nsAString & aDescription);
     NS_IMETHOD SetDescription(const nsAString & aDescription);
     NS_IMETHOD GetMacType(PRUint32 *aMacType);
     NS_IMETHOD SetMacType(PRUint32 aMacType);
     NS_IMETHOD GetMacCreator(PRUint32 *aMacCreator);
     NS_IMETHOD SetMacCreator(PRUint32 aMacCreator);
     NS_IMETHOD Equals(nsIMIMEInfo *aMIMEInfo, PRBool *_retval);
@@ -86,21 +87,29 @@ class nsMIMEInfoBase : public nsIMIMEInf
     NS_IMETHOD SetPreferredApplicationHandler(nsIHandlerApp * aPreferredApplicationHandler);
     NS_IMETHOD GetDefaultDescription(nsAString & aDefaultDescription);
     NS_IMETHOD LaunchWithURI(nsIURI *aURI);
     NS_IMETHOD GetPreferredAction(nsHandlerInfoAction *aPreferredAction);
     NS_IMETHOD SetPreferredAction(nsHandlerInfoAction aPreferredAction);
     NS_IMETHOD GetAlwaysAskBeforeHandling(PRBool *aAlwaysAskBeforeHandling);
     NS_IMETHOD SetAlwaysAskBeforeHandling(PRBool aAlwaysAskBeforeHandling); 
 
+    enum HandlerClass {
+      eMIMEInfo,
+      eProtocolInfo
+    };
+
     // nsMIMEInfoBase methods
     nsMIMEInfoBase(const char *aMIMEType = "") NS_HIDDEN;
     nsMIMEInfoBase(const nsACString& aMIMEType) NS_HIDDEN;
+    nsMIMEInfoBase(const nsACString& aType, HandlerClass aClass) NS_HIDDEN;
     virtual ~nsMIMEInfoBase();        // must be virtual, as the the base class's Release should call the subclass's destructor
 
+    void SetType(const nsACString & aType) { mType = aType; }
+
     void SetMIMEType(const nsACString & aMIMEType) { mMIMEType = aMIMEType; }
 
     void SetDefaultDescription(const nsString& aDesc) { mDefaultAppDescription = aDesc; }
 
     /**
      * Copies basic data of this MIME Info Implementation to the given other
      * MIME Info. The data consists of the MIME Type, the (default) description,
      * the MacOS type and creator, and the extension list (this object's
@@ -153,16 +162,17 @@ class nsMIMEInfoBase : public nsIMIMEInf
      */
     static NS_HIDDEN_(nsresult) GetLocalFileFromURI(nsIURI *aURI,
                                                     nsILocalFile **aFile);
 
     // member variables
     nsCStringArray         mExtensions; ///< array of file extensions associated w/ this MIME obj
     nsString               mDescription; ///< human readable description
     PRUint32               mMacType, mMacCreator; ///< Mac file type and creator
+    nsCString              mType;
     nsCString              mMIMEType;
     nsCOMPtr<nsIHandlerApp> mPreferredApplication;
     nsHandlerInfoAction    mPreferredAction; ///< preferred action to associate with this type
     nsString               mPreferredAppDescription;
     nsString               mDefaultAppDescription;
     PRBool                 mAlwaysAskBeforeHandling;
 };
 
@@ -174,16 +184,18 @@ class nsMIMEInfoBase : public nsIMIMEInf
  * member variable and provides a function for setting it. For local
  * applications, launching is done using nsIProcess, native path of the file to
  * open as first argument.
  */
 class nsMIMEInfoImpl : public nsMIMEInfoBase {
   public:
     nsMIMEInfoImpl(const char *aMIMEType = "") : nsMIMEInfoBase(aMIMEType) {}
     nsMIMEInfoImpl(const nsACString& aMIMEType) : nsMIMEInfoBase(aMIMEType) {}
+    nsMIMEInfoImpl(const nsACString& aType, HandlerClass aClass) :
+      nsMIMEInfoBase(aType, aClass) {}
     virtual ~nsMIMEInfoImpl() {}
 
     // nsIMIMEInfo methods
     NS_IMETHOD GetHasDefaultHandler(PRBool *_retval);
     NS_IMETHOD GetDefaultDescription(nsAString& aDefaultDescription);
 
     // additional methods
     /**
--- a/uriloader/exthandler/os2/nsMIMEInfoOS2.h
+++ b/uriloader/exthandler/os2/nsMIMEInfoOS2.h
@@ -39,16 +39,18 @@
 
 #include "nsMIMEInfoImpl.h"
 
 class nsMIMEInfoOS2 : public nsMIMEInfoImpl
 {
   public:
     nsMIMEInfoOS2(const char* aType = "") : nsMIMEInfoImpl(aType) {}
     nsMIMEInfoOS2(const nsACString& aMIMEType) : nsMIMEInfoImpl(aMIMEType) {}
+    nsMIMEInfoOS2(const nsACString& aType, HandlerClass aClass) :
+      nsMIMEInfoImpl(aType, aClass) {}
     virtual ~nsMIMEInfoOS2();
 
     NS_IMETHOD LaunchWithURI(nsIURI* aURI);
 
 #ifdef DEBUG
   protected:
     virtual NS_HIDDEN_(nsresult) LaunchDefaultWithFile(nsIFile* aFile) {
       NS_NOTREACHED("Do not call this, use LaunchWithFile");
--- a/uriloader/exthandler/tests/unit/test_handlerService.js
+++ b/uriloader/exthandler/tests/unit/test_handlerService.js
@@ -78,16 +78,19 @@ function run_test() {
   // the OS knows about and make sure its properties are set to the proper
   // default values.
 
   var handlerInfo = mimeSvc.getFromTypeAndExtension("nonexistent/type", null);
 
   // Make sure it's also an nsIHandlerInfo.
   do_check_true(handlerInfo instanceof Ci.nsIHandlerInfo);
 
+  do_check_eq(handlerInfo.type, "nonexistent/type");
+
+  // Deprecated property, but we should still make sure it's set correctly.
   do_check_eq(handlerInfo.MIMEType, "nonexistent/type");
 
   // These three properties are the ones the handler service knows how to store.
   do_check_eq(handlerInfo.preferredAction, Ci.nsIHandlerInfo.saveToDisk);
   do_check_eq(handlerInfo.preferredApplicationHandler, null);
   do_check_true(handlerInfo.alwaysAskBeforeHandling);
 
   // These properties are initialized to default values by the service,
--- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
@@ -1678,17 +1678,18 @@ nsOSHelperAppService::GetProtocolInfoFro
 {
   NS_ASSERTION(!aScheme.IsEmpty(), "No scheme was specified!");
 
   PRBool exists;
   nsresult rv = OSProtocolHandlerExists(nsPromiseFlatCString(aScheme).get(),
                                         &exists);
   NS_ENSURE_SUCCESS(rv, nsnull);
 
-  nsMIMEInfoImpl *handlerInfo = new nsMIMEInfoImpl();
+  nsMIMEInfoImpl *handlerInfo =
+    new nsMIMEInfoImpl(aScheme, nsMIMEInfoBase::eProtocolInfo);
   NS_ENSURE_TRUE(handlerInfo, nsnull);
   NS_ADDREF(handlerInfo);
 
   nsAutoString desc;
   GetApplicationDescription(aScheme, desc);
   handlerInfo->SetDefaultDescription(desc);
 
   return handlerInfo;
--- a/uriloader/exthandler/win/nsMIMEInfoWin.h
+++ b/uriloader/exthandler/win/nsMIMEInfoWin.h
@@ -39,16 +39,18 @@
 
 #include "nsMIMEInfoImpl.h"
 #include "nsIPropertyBag.h"
 
 class nsMIMEInfoWin : public nsMIMEInfoBase, public nsIPropertyBag {
   public:
     nsMIMEInfoWin(const char* aType = "") : nsMIMEInfoBase(aType) {}
     nsMIMEInfoWin(const nsACString& aMIMEType) : nsMIMEInfoBase(aMIMEType) {}
+    nsMIMEInfoWin(const nsACString& aType, HandlerClass aClass) :
+      nsMIMEInfoImpl(aType, aClass) {}
     virtual ~nsMIMEInfoWin();
 
     NS_IMETHOD GetHasDefaultHandler(PRBool * _retval);
 
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIPROPERTYBAG
 
     void SetDefaultApplicationHandler(nsIFile* aDefaultApplication) 
--- a/uriloader/exthandler/win/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/win/nsOSHelperAppService.cpp
@@ -593,17 +593,18 @@ nsOSHelperAppService::GetProtocolInfoFro
 {
   NS_ASSERTION(!aScheme.IsEmpty(), "No scheme was specified!");
 
   PRBool exists;
   nsresult rv = OSProtocolHandlerExists(nsPromiseFlatCString(aScheme).get(),
                                         &exists);
   NS_ENSURE_SUCCESS(rv, nsnull);
 
-  nsMIMEInfoWin *handlerInfo = new nsMIMEInfoWin();
+  nsMIMEInfoWin *handlerInfo =
+    new nsMIMEInfoWin(aScheme, nsMIMEInfoBase::eProtocolInfo);
   NS_ENSURE_TRUE(handlerInfo, nsnull);
   NS_ADDREF(handlerInfo);
 
   nsAutoString desc;
   GetApplicationDescription(aScheme, desc);
   handlerInfo->SetDefaultDescription(desc);
 
   return handlerInfo;