Bug 473045 - Update to nsIHandlerApp for win7 jump lists (plus tests). r=bz
--- a/netwerk/mime/public/nsIMIMEInfo.idl
+++ b/netwerk/mime/public/nsIMIMEInfo.idl
@@ -237,30 +237,37 @@ interface nsIMIMEInfo : nsIHandlerInfo {
/**
* nsIHandlerApp represents an external application that can handle content
* of some sort (either a MIME type or a protocol).
*
* FIXME: now that we've made nsIWebHandlerApp inherit from nsIHandlerApp,
* we should also try to make nsIWebContentHandlerInfo inherit from or possibly
* be replaced by nsIWebHandlerApp (bug 394710).
*/
-[scriptable, uuid(8d298761-0963-4c90-99e2-6ea498825e82)]
+[scriptable, uuid(8BDF20A4-9170-4548-AF52-78311A44F920)]
interface nsIHandlerApp : nsISupports {
/**
* Human readable name for the handler
*/
attribute AString name;
/**
+ * Detailed description for this handler. Suitable for
+ * a tooltip or short informative sentence.
+ */
+ attribute AString detailedDescription;
+
+ /**
* Whether or not the given handler app is logically equivalent to the
* invokant (i.e. they represent the same app).
*
* Two apps are the same if they are both either local or web handlers
- * and their executables/URI templates are the same in a string comparison.
+ * and their executables/URI templates and command line parameters are
+ * the same.
*
* @param aHandlerApp the handler app to compare to the invokant
*
* @returns true if the two are logically equivalent, false otherwise
*/
boolean equals(in nsIHandlerApp aHandlerApp);
/**
@@ -284,23 +291,62 @@ interface nsIHandlerApp : nsISupports {
void launchWithURI(in nsIURI aURI,
[optional] in nsIInterfaceRequestor aWindowContext);
};
/**
* nsILocalHandlerApp is a local OS-level executable
*/
-[scriptable, uuid(9812be73-273c-478c-8170-c3e0db08ae7c)]
+[scriptable, uuid(D36B6329-52AE-4f45-80F4-B2536AE5F8B2)]
interface nsILocalHandlerApp : nsIHandlerApp {
/**
* Pointer to the executable file used to handle content
*/
attribute nsIFile executable;
+
+ /**
+ * Returns the current number of command line parameters.
+ */
+ readonly attribute unsigned long parameterCount;
+
+ /**
+ * Clears the current list of command line parameters.
+ */
+ void clearParameters();
+
+ /**
+ * Appends a command line parameter to the command line
+ * parameter list.
+ *
+ * @param param the parameter to add.
+ */
+ void appendParameter(in AString param);
+
+ /**
+ * Retrieves a specific command line parameter.
+ *
+ * @param param the index of the parameter to return.
+ *
+ * @return the parameter string.
+ *
+ * @throw NS_ERROR_INVALID_ARG if the index is out of range.
+ */
+ AString getParameter(in unsigned long parameterIndex);
+
+ /**
+ * Checks to see if a parameter exists in the command line
+ * parameter list.
+ *
+ * @param param the parameter to search for.
+ *
+ * @return TRUE if the parameter exists in the current list.
+ */
+ boolean parameterExists(in AString param);
};
/**
* 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.
*/
--- a/uriloader/exthandler/nsDBusHandlerApp.cpp
+++ b/uriloader/exthandler/nsDBusHandlerApp.cpp
@@ -68,16 +68,30 @@ NS_IMETHODIMP nsDBusHandlerApp::GetName(
}
NS_IMETHODIMP nsDBusHandlerApp::SetName(const nsAString & aName)
{
mName.Assign(aName);
return NS_OK;
}
+NS_IMETHODIMP nsDBusHandlerApp::SetDetailedDescription(const nsAString & aDescription)
+{
+ mDetailedDescription.Assign(aDescription);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsDBusHandlerApp::GetDetailedDescription(nsAString& aDescription)
+{
+ aDescription.Assign(mDetailedDescription);
+
+ return NS_OK;
+}
+
NS_IMETHODIMP
nsDBusHandlerApp::Equals(nsIHandlerApp *aHandlerApp, PRBool *_retval)
{
NS_ENSURE_ARG_POINTER(aHandlerApp);
// If the handler app isn't a dbus handler app, then it's not the same app.
nsCOMPtr<nsIDBusHandlerApp> dbusHandlerApp = do_QueryInterface(aHandlerApp);
if (!dbusHandlerApp) {
--- a/uriloader/exthandler/nsDBusHandlerApp.h
+++ b/uriloader/exthandler/nsDBusHandlerApp.h
@@ -51,15 +51,16 @@ public:
NS_DECL_NSIDBUSHANDLERAPP
nsDBusHandlerApp() { }
virtual ~nsDBusHandlerApp() { }
protected:
nsString mName;
+ nsString mDetailedDescription;
nsCString mService;
nsCString mMethod;
nsCString mInterface;
nsCString mObjpath;
};
#endif
--- a/uriloader/exthandler/nsLocalHandlerApp.cpp
+++ b/uriloader/exthandler/nsLocalHandlerApp.cpp
@@ -65,34 +65,72 @@ NS_IMETHODIMP nsLocalHandlerApp::GetName
NS_IMETHODIMP nsLocalHandlerApp::SetName(const nsAString & aName)
{
mName.Assign(aName);
return NS_OK;
}
NS_IMETHODIMP
+nsLocalHandlerApp::SetDetailedDescription(const nsAString & aDescription)
+{
+ mDetailedDescription.Assign(aDescription);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalHandlerApp::GetDetailedDescription(nsAString& aDescription)
+{
+ aDescription.Assign(mDetailedDescription);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsLocalHandlerApp::Equals(nsIHandlerApp *aHandlerApp, PRBool *_retval)
{
NS_ENSURE_ARG_POINTER(aHandlerApp);
+ *_retval = PR_FALSE;
+
// If the handler app isn't a local handler app, then it's not the same app.
nsCOMPtr <nsILocalHandlerApp> localHandlerApp = do_QueryInterface(aHandlerApp);
- if (!localHandlerApp) {
- *_retval = PR_FALSE;
+ if (!localHandlerApp)
return NS_OK;
- }
// If either handler app doesn't have an executable, then they aren't
// the same app.
nsCOMPtr<nsIFile> executable;
nsresult rv = localHandlerApp->GetExecutable(getter_AddRefs(executable));
- if (NS_FAILED(rv) || !executable || !mExecutable) {
- *_retval = PR_FALSE;
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Equality for two empty nsIHandlerApp
+ if (!executable && !mExecutable) {
+ *_retval = PR_TRUE;
+ return NS_OK;
+ }
+
+ // At least one is set so they are not equal
+ if (!mExecutable || !executable)
return NS_OK;
+
+ // Check the command line parameter list lengths
+ PRUint32 len;
+ localHandlerApp->GetParameterCount(&len);
+ if (mParameters.Length() != len)
+ return NS_OK;
+
+ // Check the command line params lists
+ for (PRUint32 idx = 0; idx < mParameters.Length(); idx++) {
+ nsAutoString param;
+ if (NS_FAILED(localHandlerApp->GetParameter(idx, param)) ||
+ !param.Equals(mParameters[idx]))
+ return NS_OK;
}
return executable->Equals(mExecutable, _retval);
}
NS_IMETHODIMP
nsLocalHandlerApp::LaunchWithURI(nsIURI *aURI,
nsIInterfaceRequestor *aWindowContext)
@@ -117,20 +155,65 @@ nsLocalHandlerApp::LaunchWithIProcess(co
const char *string = aArg.get();
return process->Run(PR_FALSE, &string, 1);
}
////////////////////////////////////////////////////////////////////////////////
//// nsILocalHandlerApp
-NS_IMETHODIMP nsLocalHandlerApp::GetExecutable(nsIFile **aExecutable)
+/* attribute nsIFile executable; */
+NS_IMETHODIMP
+nsLocalHandlerApp::GetExecutable(nsIFile **aExecutable)
{
NS_IF_ADDREF(*aExecutable = mExecutable);
return NS_OK;
}
-NS_IMETHODIMP nsLocalHandlerApp::SetExecutable(nsIFile *aExecutable)
+NS_IMETHODIMP
+nsLocalHandlerApp::SetExecutable(nsIFile *aExecutable)
{
mExecutable = aExecutable;
return NS_OK;
}
+/* readonly attribute unsigned long parameterCount; */
+NS_IMETHODIMP
+nsLocalHandlerApp::GetParameterCount(PRUint32 *aParameterCount)
+{
+ *aParameterCount = mParameters.Length();
+ return NS_OK;
+}
+
+/* void clearParameters (); */
+NS_IMETHODIMP
+nsLocalHandlerApp::ClearParameters()
+{
+ mParameters.Clear();
+ return NS_OK;
+}
+
+/* void appendParameter (in AString param); */
+NS_IMETHODIMP
+nsLocalHandlerApp::AppendParameter(const nsAString & aParam)
+{
+ mParameters.AppendElement(aParam);
+ return NS_OK;
+}
+
+/* AString getParameter (in unsigned long parameterIndex); */
+NS_IMETHODIMP
+nsLocalHandlerApp::GetParameter(PRUint32 parameterIndex, nsAString & _retval)
+{
+ if (mParameters.Length() <= parameterIndex)
+ return NS_ERROR_INVALID_ARG;
+
+ _retval.Assign(mParameters[parameterIndex]);
+ return NS_OK;
+}
+
+/* boolean parameterExists (in AString param); */
+NS_IMETHODIMP
+nsLocalHandlerApp::ParameterExists(const nsAString & aParam, PRBool *_retval)
+{
+ *_retval = mParameters.Contains(aParam);
+ return NS_OK;
+}
--- a/uriloader/exthandler/nsLocalHandlerApp.h
+++ b/uriloader/exthandler/nsLocalHandlerApp.h
@@ -38,16 +38,17 @@
* ***** END LICENSE BLOCK ***** */
#ifndef __nsLocalHandlerAppImpl_h__
#define __nsLocalHandlerAppImpl_h__
#include "nsString.h"
#include "nsIMIMEInfo.h"
#include "nsIFile.h"
+#include "nsTArray.h"
class nsLocalHandlerApp : public nsILocalHandlerApp
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIHANDLERAPP
NS_DECL_NSILOCALHANDLERAPP
@@ -57,28 +58,29 @@ public:
: mName(aName), mExecutable(aExecutable) { }
nsLocalHandlerApp(const nsAString & aName, nsIFile *aExecutable)
: mName(aName), mExecutable(aExecutable) { }
virtual ~nsLocalHandlerApp() { }
protected:
nsString mName;
+ nsString mDetailedDescription;
+ nsTArray<nsString> mParameters;
nsCOMPtr<nsIFile> mExecutable;
/**
* Launches this application with a single argument (typically either
* a file path or a URI spec). This is meant as a helper method for
* implementations of (e.g.) LaunchWithURI.
*
* @param aApp The application to launch (may not be null)
* @param aArg The argument to pass on the command line
*/
- NS_HIDDEN_(nsresult) LaunchWithIProcess(const nsCString &aArg);
-
+ NS_HIDDEN_(nsresult) LaunchWithIProcess(const nsCString &aArg);
};
// any platforms that need a platform-specific class instead of just
// using nsLocalHandlerApp need to add an include and a typedef here.
#ifdef XP_MACOSX
# ifndef NSLOCALHANDLERAPPMAC_H_
# include "mac/nsLocalHandlerAppMac.h"
typedef nsLocalHandlerAppMac PlatformLocalHandlerApp_t;
--- a/uriloader/exthandler/nsWebHandlerApp.js
+++ b/uriloader/exthandler/nsWebHandlerApp.js
@@ -55,29 +55,38 @@ nsWebHandlerApp.prototype = {
//////////////////////////////////////////////////////////////////////////////
//// nsWebHandler
classDescription: "A web handler for protocols and content",
classID: Components.ID("8b1ae382-51a9-4972-b930-56977a57919d"),
contractID: "@mozilla.org/uriloader/web-handler-app;1",
_name: null,
+ _detailedDescription: null,
_uriTemplate: null,
//////////////////////////////////////////////////////////////////////////////
//// nsIHandlerApp
get name() {
return this._name;
},
set name(aName) {
this._name = aName;
},
+ get detailedDescription() {
+ return this._detailedDescription;
+ },
+
+ set detailedDescription(aDesc) {
+ this._detailedDescription = aDesc;
+ },
+
equals: function(aHandlerApp) {
if (!aHandlerApp)
throw Cr.NS_ERROR_NULL_POINTER;
if (aHandlerApp instanceof Ci.nsIWebHandlerApp &&
aHandlerApp.uriTemplate &&
this.uriTemplate &&
aHandlerApp.uriTemplate == this.uriTemplate)
--- a/uriloader/exthandler/tests/unit/test_handlerService.js
+++ b/uriloader/exthandler/tests/unit/test_handlerService.js
@@ -337,16 +337,80 @@ function run_test() {
do_check_eq(possibleHandlersInfo.possibleApplicationHandlers.length, 1);
// Make sure the handler is the one we didn't remove.
webPossibleHandler = possibleHandlersInfo.possibleApplicationHandlers.
queryElementAt(0, Ci.nsIWebHandlerApp);
do_check_eq(webPossibleHandler.name, webHandler.name);
do_check_true(webPossibleHandler.equals(webHandler));
+ //////////////////////////////////////////////////////
+ // handler info command line parameters and equality
+ var localApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+ createInstance(Ci.nsILocalHandlerApp);
+ var handlerApp = localApp.QueryInterface(Ci.nsIHandlerApp);
+
+ do_check_true(handlerApp.equals(localApp));
+
+ localApp.executable = executable;
+
+ do_check_eq(0, localApp.parameterCount);
+ localApp.appendParameter("-test1");
+ do_check_eq(1, localApp.parameterCount);
+ localApp.appendParameter("-test2");
+ do_check_eq(2, localApp.parameterCount);
+ do_check_true(localApp.parameterExists("-test1"));
+ do_check_true(localApp.parameterExists("-test2"));
+ do_check_false(localApp.parameterExists("-false"));
+ localApp.clearParameters();
+ do_check_eq(0, localApp.parameterCount);
+
+ var localApp2 = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+ createInstance(Ci.nsILocalHandlerApp);
+
+ localApp2.executable = executable;
+
+ localApp.clearParameters();
+ do_check_true(localApp.equals(localApp2));
+
+ // equal:
+ // cut -d 1 -f 2
+ // cut -d 1 -f 2
+
+ localApp.appendParameter("-test1");
+ localApp.appendParameter("-test2");
+ localApp.appendParameter("-test3");
+ localApp2.appendParameter("-test1");
+ localApp2.appendParameter("-test2");
+ localApp2.appendParameter("-test3");
+ do_check_true(localApp.equals(localApp2));
+
+ // not equal:
+ // cut -d 1 -f 2
+ // cut -f 1 -d 2
+
+ localApp.clearParameters();
+ localApp2.clearParameters();
+
+ localApp.appendParameter("-test1");
+ localApp.appendParameter("-test2");
+ localApp.appendParameter("-test3");
+ localApp2.appendParameter("-test2");
+ localApp2.appendParameter("-test1");
+ localApp2.appendParameter("-test3");
+ do_check_false(localApp2.equals(localApp));
+
+ var str;
+ str = localApp.getParameter(0)
+ do_check_eq(str, "-test1");
+ str = localApp.getParameter(1)
+ do_check_eq(str, "-test2");
+ str = localApp.getParameter(2)
+ do_check_eq(str, "-test3");
+
// FIXME: test round trip integrity for a protocol.
// FIXME: test round trip integrity for a handler info with a web handler.
//**************************************************************************//
// getTypeFromExtension tests
// test non-existent extension
var lolType = handlerSvc.getTypeFromExtension("lolcat");