1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/basictypes.h" 6 #include "base/bind.h" 7 #include "base/location.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/run_loop.h" 11 #include "base/time/time.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "webkit/browser/fileapi/timed_task_helper.h" 14 15 using fileapi::TimedTaskHelper; 16 17 namespace content { 18 19 namespace { 20 21 class Embedder { 22 public: 23 Embedder() 24 : timer_(base::MessageLoopProxy::current().get()), timer_fired_(false) {} 25 26 void OnTimerFired() { 27 timer_fired_ = true; 28 } 29 30 TimedTaskHelper* timer() { return &timer_; } 31 bool timer_fired() const { return timer_fired_; } 32 33 private: 34 TimedTaskHelper timer_; 35 bool timer_fired_; 36 }; 37 38 } // namespace 39 40 TEST(TimedTaskHelper, FireTimerWhenAlive) { 41 base::MessageLoop message_loop; 42 Embedder embedder; 43 44 ASSERT_FALSE(embedder.timer_fired()); 45 ASSERT_FALSE(embedder.timer()->IsRunning()); 46 47 embedder.timer()->Start( 48 FROM_HERE, 49 base::TimeDelta::FromSeconds(0), 50 base::Bind(&Embedder::OnTimerFired, base::Unretained(&embedder))); 51 52 ASSERT_TRUE(embedder.timer()->IsRunning()); 53 embedder.timer()->Reset(); 54 ASSERT_TRUE(embedder.timer()->IsRunning()); 55 56 base::RunLoop().RunUntilIdle(); 57 58 ASSERT_TRUE(embedder.timer_fired()); 59 } 60 61 TEST(TimedTaskHelper, FireTimerWhenAlreadyDeleted) { 62 base::MessageLoop message_loop; 63 64 // Run message loop after embedder is already deleted to make sure callback 65 // doesn't cause a crash for use after free. 66 { 67 Embedder embedder; 68 69 ASSERT_FALSE(embedder.timer_fired()); 70 ASSERT_FALSE(embedder.timer()->IsRunning()); 71 72 embedder.timer()->Start( 73 FROM_HERE, 74 base::TimeDelta::FromSeconds(0), 75 base::Bind(&Embedder::OnTimerFired, base::Unretained(&embedder))); 76 77 ASSERT_TRUE(embedder.timer()->IsRunning()); 78 } 79 80 // At this point the callback is still in the message queue but 81 // embedder is gone. 82 base::RunLoop().RunUntilIdle(); 83 } 84 85 } // namespace content 86