Moved the calls to the MessageLoop destruction observers to after the pending tasks are deleted.

BUG=None
TEST=Unit-test provided, tests should pass and all hell should not break loose.


Review URL: http://codereview.chromium.org/5318003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67623 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/message_loop_unittest.cc b/base/message_loop_unittest.cc
index a3c3307..537c606 100644
--- a/base/message_loop_unittest.cc
+++ b/base/message_loop_unittest.cc
@@ -1647,3 +1647,67 @@
 }  // namespace
 
 #endif  // defined(OS_POSIX)
+
+namespace {
+class RunAtDestructionTask : public Task {
+ public:
+  RunAtDestructionTask(bool* task_destroyed, bool* destruction_observer_called)
+      : task_destroyed_(task_destroyed),
+        destruction_observer_called_(destruction_observer_called) {
+  }
+  ~RunAtDestructionTask() {
+    EXPECT_FALSE(*destruction_observer_called_);
+    *task_destroyed_ = true;
+  }
+  virtual void Run() {
+    // This task should never run.
+    ADD_FAILURE();
+  }
+ private:
+  bool* task_destroyed_;
+  bool* destruction_observer_called_;
+};
+
+class MLDestructionObserver : public MessageLoop::DestructionObserver {
+ public:
+  MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
+      : task_destroyed_(task_destroyed),
+        destruction_observer_called_(destruction_observer_called),
+        task_destroyed_before_message_loop_(false) {
+  }
+  virtual void WillDestroyCurrentMessageLoop() {
+    task_destroyed_before_message_loop_ = *task_destroyed_;
+    *destruction_observer_called_ = true;
+  }
+  bool task_destroyed_before_message_loop() const {
+    return task_destroyed_before_message_loop_;
+  }
+ private:
+  bool* task_destroyed_;
+  bool* destruction_observer_called_;
+  bool task_destroyed_before_message_loop_;
+};
+
+}  // namespace
+
+TEST(MessageLoopTest, DestructionObserverTest) {
+  // Verify that the destruction observer gets called at the very end (after
+  // all the pending tasks have been destroyed).
+  MessageLoop* loop = new MessageLoop;
+  const int kDelayMS = 100;
+
+  bool task_destroyed = false;
+  bool destruction_observer_called = false;
+
+  MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
+  loop->AddDestructionObserver(&observer);
+  loop->PostDelayedTask(
+      FROM_HERE,
+      new RunAtDestructionTask(&task_destroyed, &destruction_observer_called),
+      kDelayMS);
+  delete loop;
+  EXPECT_TRUE(observer.task_destroyed_before_message_loop());
+  // The task should have been destroyed when we deleted the loop.
+  EXPECT_TRUE(task_destroyed);
+  EXPECT_TRUE(destruction_observer_called);
+}