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(); |
} |
} |