| Index: third_party/WebKit/Source/platform/LifecycleNotifier.h
|
| diff --git a/third_party/WebKit/Source/platform/LifecycleNotifier.h b/third_party/WebKit/Source/platform/LifecycleNotifier.h
|
| index 4dde3ba390e89747c922e35b0a77dd94b9ed0b00..4589d8df6aff770a17ce3cbf716bb094e6823ed5 100644
|
| --- a/third_party/WebKit/Source/platform/LifecycleNotifier.h
|
| +++ b/third_party/WebKit/Source/platform/LifecycleNotifier.h
|
| @@ -42,10 +42,12 @@ class LifecycleNotifier : public virtual GarbageCollectedMixin {
|
| void removeObserver(Observer*);
|
|
|
| // notifyContextDestroyed() should be explicitly dispatched from an
|
| - // observed context to notify observers that contextDestroyed().
|
| + // observed context to detach its observers, and if the observer kind
|
| + // requires it, notify each observer by invoking contextDestroyed().
|
| //
|
| - // When contextDestroyed() is called, the observer's lifecycleContext()
|
| - // is still valid and safe to use during the notification.
|
| + // When contextDestroyed() is called, it is supplied the context as
|
| + // an argument, but the observer's lifecycleContext() is still valid
|
| + // and safe to use while handling the notification.
|
| virtual void notifyContextDestroyed();
|
|
|
| DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_observers); }
|
| @@ -82,6 +84,51 @@ inline LifecycleNotifier<T, Observer>::~LifecycleNotifier() {
|
| // ASSERT(!m_observers.size());
|
| }
|
|
|
| +// Determine if |contextDestroyed(Observer*) is a public method on
|
| +// class type |Observer|, or any of the class types it derives from.
|
| +template <typename Observer, typename T>
|
| +class HasContextDestroyed {
|
| + using YesType = char;
|
| + using NoType = int;
|
| +
|
| + template <typename V>
|
| + static YesType checkHasContextDestroyedMethod(
|
| + V* observer,
|
| + T* context = nullptr,
|
| + typename std::enable_if<
|
| + std::is_same<decltype(observer->contextDestroyed(context)),
|
| + void>::value>::type* g = nullptr);
|
| + template <typename V>
|
| + static NoType checkHasContextDestroyedMethod(...);
|
| +
|
| + public:
|
| + static_assert(sizeof(Observer), "Observer's class declaration not in scope");
|
| + static const bool value =
|
| + sizeof(YesType) ==
|
| + sizeof(checkHasContextDestroyedMethod<Observer>(nullptr));
|
| +};
|
| +
|
| +// If |Observer::contextDestroyed()| is present, invoke it.
|
| +template <typename Observer,
|
| + typename T,
|
| + bool = HasContextDestroyed<Observer, T>::value>
|
| +class NotifyContextDestroyed {
|
| + STATIC_ONLY(NotifyContextDestroyed);
|
| +
|
| + public:
|
| + static void call(Observer* observer, T* context) {
|
| + observer->contextDestroyed(context);
|
| + }
|
| +};
|
| +
|
| +template <typename Observer, typename T>
|
| +class NotifyContextDestroyed<Observer, T, false> {
|
| + STATIC_ONLY(NotifyContextDestroyed);
|
| +
|
| + public:
|
| + static void call(Observer*, T*) {}
|
| +};
|
| +
|
| template <typename T, typename Observer>
|
| inline void LifecycleNotifier<T, Observer>::notifyContextDestroyed() {
|
| // Observer unregistration is allowed, but effectively a no-op.
|
| @@ -90,7 +137,7 @@ inline void LifecycleNotifier<T, Observer>::notifyContextDestroyed() {
|
| m_observers.swap(observers);
|
| for (Observer* observer : observers) {
|
| DCHECK(observer->lifecycleContext() == context());
|
| - observer->contextDestroyed(context());
|
| + NotifyContextDestroyed<Observer, T>::call(observer, context());
|
| observer->clearContext();
|
| }
|
| }
|
|
|