diff options
Diffstat (limited to 'comm/mailnews/base/src/UrlListener.h')
-rw-r--r-- | comm/mailnews/base/src/UrlListener.h | 72 |
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__ |