summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-12 13:21:21 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-12 13:21:21 +0000
commit6719948d489335b4b679c190a59e4995244a00e0 (patch)
treed19392a9ddf91bf824999c24e7bfef7b4e3a721d /webkit
parentb7823011f3bf858a0d4baba1252f31831b3f3555 (diff)
downloadchromium_src-6719948d489335b4b679c190a59e4995244a00e0.zip
chromium_src-6719948d489335b4b679c190a59e4995244a00e0.tar.gz
chromium_src-6719948d489335b4b679c190a59e4995244a00e0.tar.bz2
Add TimedTaskHelper to replace timer on SequencedTaskRunner
The code is based on the ObfuscatedFileUtil's ex-timer code that replaces timer with PostDelayTask. BUG=248826 R=tzik@chromium.org Review URL: https://codereview.chromium.org/16775011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205748 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/browser/fileapi/timed_task_helper.cc91
-rw-r--r--webkit/browser/fileapi/timed_task_helper.h59
-rw-r--r--webkit/browser/fileapi/timed_task_helper_unittest.cc84
-rw-r--r--webkit/storage_browser.gyp2
4 files changed, 236 insertions, 0 deletions
diff --git a/webkit/browser/fileapi/timed_task_helper.cc b/webkit/browser/fileapi/timed_task_helper.cc
new file mode 100644
index 0000000..7a33a6a
--- /dev/null
+++ b/webkit/browser/fileapi/timed_task_helper.cc
@@ -0,0 +1,91 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/timed_task_helper.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/sequenced_task_runner.h"
+
+namespace fileapi {
+
+struct TimedTaskHelper::Tracker {
+ explicit Tracker(TimedTaskHelper* timer) : timer(timer) {}
+
+ ~Tracker() {
+ if (timer)
+ timer->tracker_ = NULL;
+ }
+
+ TimedTaskHelper* timer;
+};
+
+TimedTaskHelper::TimedTaskHelper(base::SequencedTaskRunner* task_runner)
+ : task_runner_(task_runner),
+ tracker_(NULL) {
+}
+
+TimedTaskHelper::~TimedTaskHelper() {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ if (tracker_)
+ tracker_->timer = NULL;
+}
+
+bool TimedTaskHelper::IsRunning() const {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ return tracker_ != NULL;
+}
+
+void TimedTaskHelper::Start(
+ const tracked_objects::Location& posted_from,
+ base::TimeDelta delay,
+ const base::Closure& user_task) {
+ posted_from_ = posted_from;
+ delay_ = delay;
+ user_task_ = user_task;
+ Reset();
+}
+
+void TimedTaskHelper::Reset() {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(!user_task_.is_null());
+ desired_run_time_ = base::TimeTicks::Now() + delay_;
+
+ if (tracker_)
+ return;
+
+ // Initialize the tracker for the first time.
+ tracker_ = new Tracker(this);
+ PostDelayedTask(make_scoped_ptr(tracker_), delay_);
+}
+
+// static
+void TimedTaskHelper::Fired(scoped_ptr<Tracker> tracker) {
+ if (!tracker->timer)
+ return;
+ TimedTaskHelper* timer = tracker->timer;
+ timer->OnFired(tracker.Pass());
+}
+
+void TimedTaskHelper::OnFired(scoped_ptr<Tracker> tracker) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ base::TimeTicks now = base::TimeTicks::Now();
+ if (desired_run_time_ > now) {
+ PostDelayedTask(tracker.Pass(), desired_run_time_ - now);
+ return;
+ }
+ tracker.reset();
+ user_task_.Run();
+ user_task_.Reset();
+}
+
+void TimedTaskHelper::PostDelayedTask(scoped_ptr<Tracker> tracker,
+ base::TimeDelta delay) {
+ task_runner_->PostDelayedTask(
+ posted_from_,
+ base::Bind(&TimedTaskHelper::Fired, base::Passed(&tracker)),
+ delay);
+}
+
+} // namespace fileapi
diff --git a/webkit/browser/fileapi/timed_task_helper.h b/webkit/browser/fileapi/timed_task_helper.h
new file mode 100644
index 0000000..ad72fb8
--- /dev/null
+++ b/webkit/browser/fileapi/timed_task_helper.h
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_TIMED_TASK_HELPER_H_
+#define WEBKIT_BROWSER_FILEAPI_TIMED_TASK_HELPER_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time.h"
+#include "webkit/storage/webkit_storage_export.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace fileapi {
+
+// Works similarly as base::Timer, but takes SequencedTaskRunner and
+// runs tasks on it (instead of implicitly bound to a thread).
+// TODO(kinuko): This has nothing to do with fileapi. Move somewhere
+// more common place.
+class WEBKIT_STORAGE_EXPORT TimedTaskHelper {
+ public:
+ explicit TimedTaskHelper(base::SequencedTaskRunner* task_runner);
+ ~TimedTaskHelper();
+
+ bool IsRunning() const;
+ void Start(const tracked_objects::Location& posted_from,
+ base::TimeDelta delay,
+ const base::Closure& user_task);
+ void Reset();
+
+ private:
+ struct Tracker;
+ static void Fired(scoped_ptr<Tracker> tracker);
+
+ void OnFired(scoped_ptr<Tracker> tracker);
+ void PostDelayedTask(scoped_ptr<Tracker> tracker, base::TimeDelta delay);
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ tracked_objects::Location posted_from_;
+ base::TimeDelta delay_;
+ base::Closure user_task_;
+
+ base::TimeTicks desired_run_time_;
+
+ // This is set to non-null and owned by a timer task while timer is running.
+ Tracker* tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(TimedTaskHelper);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_TIMED_TASK_HELPER_H_
diff --git a/webkit/browser/fileapi/timed_task_helper_unittest.cc b/webkit/browser/fileapi/timed_task_helper_unittest.cc
new file mode 100644
index 0000000..5f11c7e
--- /dev/null
+++ b/webkit/browser/fileapi/timed_task_helper_unittest.cc
@@ -0,0 +1,84 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/timed_task_helper.h"
+
+namespace fileapi {
+
+namespace {
+
+class Embedder {
+ public:
+ Embedder()
+ : timer_(base::MessageLoopProxy::current()),
+ timer_fired_(false) {}
+
+ void OnTimerFired() {
+ timer_fired_ = true;
+ }
+
+ TimedTaskHelper* timer() { return &timer_; }
+ bool timer_fired() const { return timer_fired_; }
+
+ private:
+ TimedTaskHelper timer_;
+ bool timer_fired_;
+};
+
+} // namespace
+
+TEST(TimedTaskHelper, FireTimerWhenAlive) {
+ base::MessageLoop message_loop;
+ Embedder embedder;
+
+ ASSERT_FALSE(embedder.timer_fired());
+ ASSERT_FALSE(embedder.timer()->IsRunning());
+
+ embedder.timer()->Start(
+ FROM_HERE,
+ base::TimeDelta::FromSeconds(0),
+ base::Bind(&Embedder::OnTimerFired, base::Unretained(&embedder)));
+
+ ASSERT_TRUE(embedder.timer()->IsRunning());
+ embedder.timer()->Reset();
+ ASSERT_TRUE(embedder.timer()->IsRunning());
+
+ base::MessageLoop::current()->RunUntilIdle();
+
+ ASSERT_TRUE(embedder.timer_fired());
+}
+
+TEST(TimedTaskHelper, FireTimerWhenAlreadyDeleted) {
+ base::MessageLoop message_loop;
+
+ // Run message loop after embedder is already deleted to make sure callback
+ // doesn't cause a crash for use after free.
+ {
+ Embedder embedder;
+
+ ASSERT_FALSE(embedder.timer_fired());
+ ASSERT_FALSE(embedder.timer()->IsRunning());
+
+ embedder.timer()->Start(
+ FROM_HERE,
+ base::TimeDelta::FromSeconds(0),
+ base::Bind(&Embedder::OnTimerFired, base::Unretained(&embedder)));
+
+ ASSERT_TRUE(embedder.timer()->IsRunning());
+ }
+
+ // At this point the callback is still in the message queue but
+ // embedder is gone.
+ base::MessageLoop::current()->RunUntilIdle();
+}
+
+} // namespace fileapi
diff --git a/webkit/storage_browser.gyp b/webkit/storage_browser.gyp
index 01b0a22..59afef5 100644
--- a/webkit/storage_browser.gyp
+++ b/webkit/storage_browser.gyp
@@ -220,6 +220,8 @@
'browser/fileapi/task_runner_bound_observer_list.h',
'browser/fileapi/test_mount_point_provider.cc',
'browser/fileapi/test_mount_point_provider.h',
+ 'browser/fileapi/timed_task_helper.cc',
+ 'browser/fileapi/timed_task_helper.h',
'browser/fileapi/transient_file_util.cc',
'browser/fileapi/transient_file_util.h',
'browser/fileapi/upload_file_system_file_element_reader.cc',