summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/base/src/UrlListener.h
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/base/src/UrlListener.h')
-rw-r--r--comm/mailnews/base/src/UrlListener.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/comm/mailnews/base/src/UrlListener.h b/comm/mailnews/base/src/UrlListener.h
new file mode 100644
index 0000000000..22a0597854
--- /dev/null
+++ b/comm/mailnews/base/src/UrlListener.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef UrlListener_h__
+#define UrlListener_h__
+
+#include <functional> // For std::function.
+#include "nsIUrlListener.h"
+class nsIURI;
+
+/**
+ * UrlListener is a small nsIUrlListener implementation which allows
+ * callable objects (including lambdas) to be plugged in instead of deriving
+ * your own nsIUrlListener.
+ *
+ * The aim is to encourage more readable code by allowing the start/stop
+ * notifications of a long-running operation to be handled near to where the
+ * operation was initiated.
+ *
+ * A contrived example:
+ *
+ * void Kick() {
+ * UrlListener* listener = new UrlListener;
+ * listener->mStopFn = [](nsIURI* url, nsresult status) -> nsresult {
+ * // Note that we may get here waaaaaaay after Kick() has returned...
+ * printf("LongRunningOperation is finished.\n");
+ * return NS_OK;
+ * };
+ * thingService.startLongRunningOperation(listener);
+ * //...continue doing other stuff while operation is ongoing...
+ * }
+ *
+ * Traditionally, c-c code has tended to use multiple inheritance to add
+ * listener callbacks to the class of the object initiating the operation.
+ * This has a couple of undesirable side effects:
+ *
+ * 1) It separates out the onStopRunningUrl handling into some other
+ * part of the code, which makes the order of things much harder to follow.
+ * 2) Often the same onStopRunningUrl handler will be used for many different
+ * kinds of operations (see nsImapMailFolder::OnStopRunningUrl(), for
+ * example).
+ * 3) It exposes implementation details as part of the public interface
+ * e.g see all the listener types nsMsgDBFolder derives from to implement
+ * it's internals. That's all just confusing noise that shouldn't be seen
+ * from outside the class.
+ *
+ * Just as PromiseTestUtils.jsm brings the Javascript side up from callback
+ * hell to async lovelyness, this can be used to raise the C++ side from
+ * callback-somewhere-else-maybe-in-this-class-but-who-can-really-tell hell
+ * up to normal callback hell :-)
+ *
+ */
+class UrlListener : public nsIUrlListener {
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIURLLISTENER
+
+ UrlListener() {}
+ /**
+ * mStartFn and mStopFn are the OnStartRunning() and OnStopRunningUrl()
+ * handlers. It's fine for them to be null (often you'll only need mStopFn).
+ */
+ std::function<nsresult(nsIURI*)> mStartFn;
+ std::function<nsresult(nsIURI*, nsresult)> mStopFn;
+
+ protected:
+ virtual ~UrlListener() {}
+};
+
+#endif // UrlListener_h__