Bug 389969 - There is no protocol handling dialog. r=cbiesinger, sr=dmose, a=schrep
authorsdwilsh@shawnwilsher.com
Mon, 30 Jul 2007 16:33:16 -0700
changeset 4103 1936836fe66824c91c851a8dbe57328f41239562
parent 4102 739e80147145e116e5474399501a2ff16dc9169c
child 4104 30bb1b9edf7bc2ec876b4f66f08987d949b042c9
push idunknown
push userunknown
push dateunknown
reviewerscbiesinger, dmose, schrep
bugs389969
milestone1.9a7pre
Bug 389969 - There is no protocol handling dialog. r=cbiesinger, sr=dmose, a=schrep
netwerk/mime/public/nsIMIMEInfo.idl
uriloader/exthandler/beos/nsOSHelperAppService.cpp
uriloader/exthandler/beos/nsOSHelperAppService.h
uriloader/exthandler/mac/nsOSHelperAppService.cpp
uriloader/exthandler/mac/nsOSHelperAppService.h
uriloader/exthandler/nsExternalHelperAppService.cpp
uriloader/exthandler/nsExternalHelperAppService.h
uriloader/exthandler/nsMIMEInfoImpl.cpp
uriloader/exthandler/unix/nsOSHelperAppService.cpp
uriloader/exthandler/unix/nsOSHelperAppService.h
uriloader/exthandler/win/nsOSHelperAppService.cpp
uriloader/exthandler/win/nsOSHelperAppService.h
--- a/netwerk/mime/public/nsIMIMEInfo.idl
+++ b/netwerk/mime/public/nsIMIMEInfo.idl
@@ -100,16 +100,20 @@ interface nsIHandlerInfo : nsISupports {
      * 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;
+    /**
+     * Used to indicate that we know nothing about what to do with this.  You
+     * could consider this to be not initialized.
+     */
     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.
--- a/uriloader/exthandler/beos/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/beos/nsOSHelperAppService.cpp
@@ -228,30 +228,36 @@ nsOSHelperAppService::GetMIMEInfoFromOS(
   NS_ADDREF(mi);
   if (!aFileExt.IsEmpty())
     mi->AppendExtension(aFileExt);
 
   return mi;
 }
 
 already_AddRefed<nsIHandlerInfo>
-nsOSHelperAppService::GetProtocolInfoFromOS(const nsACString &aScheme)
+nsOSHelperAppService::GetProtocolInfoFromOS(const nsACString &aScheme,
+                                            PRBool *found)
 {
   NS_ASSERTION(!aScheme.IsEmpty(), "No scheme was specified!");
 
-  PRBool exists;
   nsresult rv = OSProtocolHandlerExists(nsPromiseFlatCString(aScheme).get(),
-                                        &exists);
-  if (NS_FAILED(rv) || !exists)
+                                        found);
+  if (NS_FAILED(rv))
     return nsnull;
 
   nsMIMEInfoBeOS *handlerInfo =
 	new nsMIMEInfoBeOS(aScheme, nsMIMEInfoBase::eProtocolInfo);
   NS_ENSURE_TRUE(handlerInfo, nsnull);
   NS_ADDREF(handlerInfo);
 
+  if (!*found) {
+    // Code that calls this requires an object regardless if the OS has
+    // something for us, so we return the empty object.
+    return handlerInfo;
+  }
+
   nsAutoString desc;
   GetApplicationDescription(aScheme, desc);
   handlerInfo->SetDefaultDescription(desc);
 
   return handlerInfo;
 }
 
--- a/uriloader/exthandler/beos/nsOSHelperAppService.h
+++ b/uriloader/exthandler/beos/nsOSHelperAppService.h
@@ -49,17 +49,18 @@ class nsMIMEInfoBeOS;
 
 class nsOSHelperAppService : public nsExternalHelperAppService
 {
 public:
 	nsOSHelperAppService();
 	virtual ~nsOSHelperAppService();
 
 	already_AddRefed<nsIMIMEInfo> GetMIMEInfoFromOS(const nsACString& aMIMEType, const nsACString& aFileExt, PRBool *aFound);
-	already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme);
+	already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme,
+	                                                       PRBool *found);
 
 	// override nsIExternalProtocolService methods
 	nsresult OSProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists);
 
 protected:
 	nsresult SetMIMEInfoForType(const char *aMIMEType, nsMIMEInfoBeOS **_retval);
 	nsresult GetMimeInfoFromExtension(const char *aFileExt, nsMIMEInfoBeOS **_retval);
 	nsresult GetMimeInfoFromMIMEType(const char *aMIMEType, nsMIMEInfoBeOS **_retval);
--- a/uriloader/exthandler/mac/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/mac/nsOSHelperAppService.cpp
@@ -311,31 +311,37 @@ nsOSHelperAppService::GetMIMEInfoFromOS(
     if (!aFileExt.IsEmpty())
       mimeInfo->AppendExtension(aFileExt);
   }
   
   return mimeInfo;
 }
 
 already_AddRefed<nsIHandlerInfo>
-nsOSHelperAppService::GetProtocolInfoFromOS(const nsACString &aScheme)
+nsOSHelperAppService::GetProtocolInfoFromOS(const nsACString &aScheme,
+                                            PRBool *found)
 {
   NS_ASSERTION(!aScheme.IsEmpty(), "No scheme was specified!");
 
-  PRBool exists;
   nsresult rv = OSProtocolHandlerExists(nsPromiseFlatCString(aScheme).get(),
-                                        &exists);
-  if (NS_FAILED(rv) || !exists)
+                                        found);
+  if (NS_FAILED(rv))
     return nsnull;
 
   nsMIMEInfoMac *handlerInfo =
     new nsMIMEInfoMac(aScheme, nsMIMEInfoBase::eProtocolInfo);
   NS_ENSURE_TRUE(handlerInfo, nsnull);
   NS_ADDREF(handlerInfo);
 
+  if (!*found) {
+    // Code that calls this requires an object regardless if the OS has
+    // something for us, so we return the empty object.
+    return handlerInfo;
+  }
+
   nsAutoString desc;
   GetApplicationDescription(aScheme, desc);
   handlerInfo->SetDefaultDescription(desc);
 
   return handlerInfo;
 }
 
 // we never want to use a hard coded value for the creator and file type for the mac. always look these values up
--- a/uriloader/exthandler/mac/nsOSHelperAppService.h
+++ b/uriloader/exthandler/mac/nsOSHelperAppService.h
@@ -56,17 +56,18 @@ public:
   virtual ~nsOSHelperAppService();
 
   // override nsIExternalProtocolService methods
   NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval);
   
   // method overrides --> used to hook the mime service into internet config....
   NS_IMETHOD GetFromTypeAndExtension(const nsACString& aType, const nsACString& aFileExt, nsIMIMEInfo ** aMIMEInfo);
   already_AddRefed<nsIMIMEInfo> GetMIMEInfoFromOS(const nsACString& aMIMEType, const nsACString& aFileExt, PRBool * aFound);
-  already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme);
+  already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme,
+                                                         PRBool *found);
 
   // GetFileTokenForPath must be implemented by each platform. 
   // platformAppPath --> a platform specific path to an application that we got out of the 
   //                     rdf data source. This can be a mac file spec, a unix path or a windows path depending on the platform
   // aFile --> an nsIFile representation of that platform application path.
   virtual nsresult GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile);
 
   nsresult OSProtocolHandlerExists(const char * aScheme,
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -1332,31 +1332,37 @@ nsExternalHelperAppService::GetProtocolH
 
   // XXX enterprise customers should be able to turn this support off with a
   // single master pref (maybe use one of the "exposed" prefs here?)
 
   // 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.
-  *aHandlerInfo = GetProtocolInfoFromOS(aScheme).get();
+  PRBool exists;
+  *aHandlerInfo = GetProtocolInfoFromOS(aScheme, &exists).get();
   if (!(*aHandlerInfo)) {
     // Either it knows nothing, or we ran out of memory
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv = FillProtoInfoForSchemeFromDS(aScheme, *aHandlerInfo);     
   if (NS_ERROR_NOT_AVAILABLE == rv) {
     // We don't know it, so we always ask the user.  By the time we call this
     // method, we already have checked if we should open this protocol and ask
     // the user, so these defaults are OK.
     // XXX this is a bit different than the MIME system, so we may want to look
     //     into this more in the future.
-    (*aHandlerInfo)->SetPreferredAction(nsIHandlerInfo::useSystemDefault);
     (*aHandlerInfo)->SetAlwaysAskBeforeHandling(PR_TRUE);
+    // If no OS default existed, we set the preferred action to alwaysAsk.  This
+    // really means not initialized to all the code...
+    if (exists)
+      (*aHandlerInfo)->SetPreferredAction(nsIHandlerInfo::useSystemDefault);
+    else
+      (*aHandlerInfo)->SetPreferredAction(nsIHandlerInfo::alwaysAsk);
   } else if (NS_FAILED(rv)) {
     NS_RELEASE(*aHandlerInfo);
     return rv;
   }
 
   return NS_OK;
 }
  
--- a/uriloader/exthandler/nsExternalHelperAppService.h
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
@@ -199,17 +199,18 @@ public:
 
   /**
    * Given a scheme, looks up the protocol info from the OS.  This should be
    * overridden by each OS's implementation.
    *
    * @param aScheme The protocol scheme we are looking for.
    * @return An nsIHanderInfo for the protocol.
    */
-  virtual already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme) = 0;
+  virtual already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme,
+                                                                 PRBool *found) = 0;
 
   /**
    * Given a string identifying an application, create an nsIFile representing
    * it. This function should look in $PATH for the application.
    * The base class implementation will first try to interpret platformAppPath
    * as an absolute path, and if that fails it will look for a file next to the
    * mozilla executable. Subclasses can override this method if they want a
    * different behaviour.
--- a/uriloader/exthandler/nsMIMEInfoImpl.cpp
+++ b/uriloader/exthandler/nsMIMEInfoImpl.cpp
@@ -444,17 +444,17 @@ nsMIMEInfoImpl::GetDefaultDescription(ns
   }
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMIMEInfoImpl::GetHasDefaultHandler(PRBool * _retval)
 {
-  *_retval = PR_FALSE;
+  *_retval = !mDefaultAppDescription.IsEmpty();
   if (mDefaultApplication) {
     PRBool exists;
     *_retval = NS_SUCCEEDED(mDefaultApplication->Exists(&exists)) && exists;
   }
   return NS_OK;
 }
 
 nsresult
--- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
@@ -1630,34 +1630,40 @@ nsOSHelperAppService::GetMIMEInfoFromOS(
     retval->CopyBasicDataTo(miByExt);
 
     miByExt.swap(retval);
   }
   return retval;
 }
 
 already_AddRefed<nsIHandlerInfo>
-nsOSHelperAppService::GetProtocolInfoFromOS(const nsACString &aScheme)
+nsOSHelperAppService::GetProtocolInfoFromOS(const nsACString &aScheme,
+                                            PRBool *found)
 {
   NS_ASSERTION(!aScheme.IsEmpty(), "No scheme was specified!");
 
   // We must check that a registered handler exists so that gnome_url_show
   // doesn't fallback to gnomevfs.
   // See nsGNOMERegistry::LoadURL and bug 389632.
-  PRBool exists;
   nsresult rv = OSProtocolHandlerExists(nsPromiseFlatCString(aScheme).get(),
-                                        &exists);
-  if (NS_FAILED(rv) || !exists)
+                                        found);
+  if (NS_FAILED(rv))
     return nsnull;
 
   nsMIMEInfoUnix *handlerInfo =
     new nsMIMEInfoUnix(aScheme, nsMIMEInfoBase::eProtocolInfo);
   NS_ENSURE_TRUE(handlerInfo, nsnull);
   NS_ADDREF(handlerInfo);
 
+  if (!*found) {
+    // Code that calls this requires an object regardless if the OS has
+    // something for us, so we return the empty object.
+    return handlerInfo;
+  }
+
   nsAutoString desc;
   GetApplicationDescription(aScheme, desc);
   handlerInfo->SetDefaultDescription(desc);
 
   return handlerInfo;
 }
 
 void
--- a/uriloader/exthandler/unix/nsOSHelperAppService.h
+++ b/uriloader/exthandler/unix/nsOSHelperAppService.h
@@ -56,17 +56,18 @@ class nsOSHelperAppService : public nsEx
 public:
   nsOSHelperAppService();
   virtual ~nsOSHelperAppService();
 
   // method overrides for mime.types and mime.info look up steps
   already_AddRefed<nsIMIMEInfo> GetMIMEInfoFromOS(const nsACString& aMimeType,
                                                   const nsACString& aFileExt,
                                                   PRBool     *aFound);
-  already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme);
+  already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme,
+                                                         PRBool *found);
 
   // override nsIExternalProtocolService methods
   nsresult OSProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists);
   NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval);
 
   // GetFileTokenForPath must be implemented by each platform. 
   // platformAppPath --> a platform specific path to an application that we got out of the 
   //                     rdf data source. This can be a mac file spec, a unix path or a windows path depending on the platform
--- a/uriloader/exthandler/win/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/win/nsOSHelperAppService.cpp
@@ -549,30 +549,36 @@ already_AddRefed<nsIMIMEInfo> nsOSHelper
     miByExt->GetDefaultDescription(desc);
 
     mi->SetDefaultDescription(desc);
   }
   return mi;
 }
 
 already_AddRefed<nsIHandlerInfo>
-nsOSHelperAppService::GetProtocolInfoFromOS(const nsACString &aScheme)
+nsOSHelperAppService::GetProtocolInfoFromOS(const nsACString &aScheme,
+                                            PRBool *found)
 {
   NS_ASSERTION(!aScheme.IsEmpty(), "No scheme was specified!");
 
-  PRBool exists;
   nsresult rv = OSProtocolHandlerExists(nsPromiseFlatCString(aScheme).get(),
-                                        &exists);
-  if (NS_FAILED(rv) || !exists)
+                                        found);
+  if (NS_FAILED(rv))
     return nsnull;
 
   nsMIMEInfoWin *handlerInfo =
     new nsMIMEInfoWin(aScheme, nsMIMEInfoBase::eProtocolInfo);
   NS_ENSURE_TRUE(handlerInfo, nsnull);
   NS_ADDREF(handlerInfo);
 
+  if (!*found) {
+    // Code that calls this requires an object regardless if the OS has
+    // something for us, so we return the empty object.
+    return handlerInfo;
+  }
+
   nsAutoString desc;
   GetApplicationDescription(aScheme, desc);
   handlerInfo->SetDefaultDescription(desc);
 
   return handlerInfo;
 }
 
--- a/uriloader/exthandler/win/nsOSHelperAppService.h
+++ b/uriloader/exthandler/win/nsOSHelperAppService.h
@@ -58,17 +58,18 @@ public:
 
   // override nsIExternalProtocolService methods
   nsresult OSProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists);
   nsresult LoadUriInternal(nsIURI * aURL);
   NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval);
 
   // method overrides for windows registry look up steps....
   already_AddRefed<nsIMIMEInfo> GetMIMEInfoFromOS(const nsACString& aMIMEType, const nsACString& aFileExt, PRBool *aFound);
-  already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme);
+  already_AddRefed<nsIHandlerInfo> GetProtocolInfoFromOS(const nsACString &aScheme,
+                                                         PRBool *found);
 
   /** Get the string value of a registry value and store it in result.
    * @return PR_TRUE on success, PR_FALSE on failure
    */
   static PRBool GetValueString(HKEY hKey, const PRUnichar* pValueName, nsAString& result);
 
 protected:
   nsresult GetDefaultAppInfo(const nsAString& aTypeName, nsAString& aDefaultDescription, nsIFile** aDefaultApplication);