Port Android relocation packer to chromium build
[chromium-blink-merge.git] / components / sessions / base_session_service.cc
blobadc4381a32765042c356392be793efe6896b2ee8
1 // Copyright 2012 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.
5 #include "components/sessions/base_session_service.h"
7 #include "base/bind.h"
8 #include "base/threading/thread.h"
9 #include "components/sessions/base_session_service_delegate.h"
10 #include "components/sessions/session_backend.h"
12 // BaseSessionService ---------------------------------------------------------
14 namespace sessions {
15 namespace {
17 // Helper used by ScheduleGetLastSessionCommands. It runs callback on TaskRunner
18 // thread if it's not canceled.
19 void RunIfNotCanceled(
20 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
21 const BaseSessionService::GetCommandsCallback& callback,
22 ScopedVector<SessionCommand> commands) {
23 if (is_canceled.Run())
24 return;
25 callback.Run(commands.Pass());
28 void PostOrRunInternalGetCommandsCallback(
29 base::TaskRunner* task_runner,
30 const BaseSessionService::GetCommandsCallback& callback,
31 ScopedVector<SessionCommand> commands) {
32 if (task_runner->RunsTasksOnCurrentThread()) {
33 callback.Run(commands.Pass());
34 } else {
35 task_runner->PostTask(FROM_HERE,
36 base::Bind(callback, base::Passed(&commands)));
40 } // namespace
42 // Delay between when a command is received, and when we save it to the
43 // backend.
44 static const int kSaveDelayMS = 2500;
46 BaseSessionService::BaseSessionService(
47 SessionType type,
48 const base::FilePath& path,
49 BaseSessionServiceDelegate* delegate)
50 : pending_reset_(false),
51 commands_since_reset_(0),
52 delegate_(delegate),
53 sequence_token_(delegate_->GetBlockingPool()->GetSequenceToken()),
54 weak_factory_(this) {
55 backend_ = new SessionBackend(type, path);
56 DCHECK(backend_.get());
59 BaseSessionService::~BaseSessionService() {}
61 void BaseSessionService::MoveCurrentSessionToLastSession() {
62 Save();
63 RunTaskOnBackendThread(
64 FROM_HERE, base::Bind(&SessionBackend::MoveCurrentSessionToLastSession,
65 backend_));
68 void BaseSessionService::DeleteLastSession() {
69 RunTaskOnBackendThread(
70 FROM_HERE,
71 base::Bind(&SessionBackend::DeleteLastSession, backend_));
74 void BaseSessionService::ScheduleCommand(scoped_ptr<SessionCommand> command) {
75 DCHECK(command);
76 commands_since_reset_++;
77 pending_commands_.push_back(command.release());
78 StartSaveTimer();
81 void BaseSessionService::AppendRebuildCommand(
82 scoped_ptr<SessionCommand> command) {
83 DCHECK(command);
84 pending_commands_.push_back(command.release());
87 void BaseSessionService::EraseCommand(SessionCommand* old_command) {
88 ScopedVector<SessionCommand>::iterator it =
89 std::find(pending_commands_.begin(),
90 pending_commands_.end(),
91 old_command);
92 CHECK(it != pending_commands_.end());
93 pending_commands_.erase(it);
96 void BaseSessionService::SwapCommand(SessionCommand* old_command,
97 scoped_ptr<SessionCommand> new_command) {
98 ScopedVector<SessionCommand>::iterator it =
99 std::find(pending_commands_.begin(),
100 pending_commands_.end(),
101 old_command);
102 CHECK(it != pending_commands_.end());
103 *it = new_command.release();
104 delete old_command;
107 void BaseSessionService::ClearPendingCommands() {
108 pending_commands_.clear();
111 void BaseSessionService::StartSaveTimer() {
112 // Don't start a timer when testing.
113 if (delegate_->ShouldUseDelayedSave() && base::MessageLoop::current() &&
114 !weak_factory_.HasWeakPtrs()) {
115 base::MessageLoop::current()->PostDelayedTask(
116 FROM_HERE,
117 base::Bind(&BaseSessionService::Save,
118 weak_factory_.GetWeakPtr()),
119 base::TimeDelta::FromMilliseconds(kSaveDelayMS));
123 void BaseSessionService::Save() {
124 // Inform the delegate that we will save the commands now, giving it the
125 // opportunity to append more commands.
126 delegate_->OnWillSaveCommands();
128 if (pending_commands_.empty())
129 return;
131 // We create a new ScopedVector which will receive all elements from the
132 // current commands. This will also clear the current list.
133 RunTaskOnBackendThread(
134 FROM_HERE,
135 base::Bind(&SessionBackend::AppendCommands, backend_,
136 base::Passed(&pending_commands_),
137 pending_reset_));
139 if (pending_reset_) {
140 commands_since_reset_ = 0;
141 pending_reset_ = false;
144 delegate_->OnSavedCommands();
147 base::CancelableTaskTracker::TaskId
148 BaseSessionService::ScheduleGetLastSessionCommands(
149 const GetCommandsCallback& callback,
150 base::CancelableTaskTracker* tracker) {
151 base::CancelableTaskTracker::IsCanceledCallback is_canceled;
152 base::CancelableTaskTracker::TaskId id =
153 tracker->NewTrackedTaskId(&is_canceled);
155 GetCommandsCallback run_if_not_canceled =
156 base::Bind(&RunIfNotCanceled, is_canceled, callback);
158 GetCommandsCallback callback_runner =
159 base::Bind(&PostOrRunInternalGetCommandsCallback,
160 base::MessageLoopProxy::current(), run_if_not_canceled);
162 RunTaskOnBackendThread(
163 FROM_HERE,
164 base::Bind(&SessionBackend::ReadLastSessionCommands, backend_,
165 is_canceled, callback_runner));
166 return id;
169 void BaseSessionService::RunTaskOnBackendThread(
170 const tracked_objects::Location& from_here,
171 const base::Closure& task) {
172 base::SequencedWorkerPool* pool = delegate_->GetBlockingPool();
173 if (!pool->IsShutdownInProgress()) {
174 pool->PostSequencedWorkerTask(sequence_token_, from_here, task);
175 } else {
176 // Fall back to executing on the main thread if the sequence
177 // worker pool has been requested to shutdown (around shutdown
178 // time).
179 task.Run();
183 } // namespace sessions