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"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/threading/thread.h"
12 #include "components/sessions/base_session_service_delegate.h"
13 #include "components/sessions/session_backend.h"
15 // BaseSessionService ---------------------------------------------------------
20 // Helper used by ScheduleGetLastSessionCommands. It runs callback on TaskRunner
21 // thread if it's not canceled.
22 void RunIfNotCanceled(
23 const base::CancelableTaskTracker::IsCanceledCallback
& is_canceled
,
24 const BaseSessionService::GetCommandsCallback
& callback
,
25 ScopedVector
<SessionCommand
> commands
) {
26 if (is_canceled
.Run())
28 callback
.Run(commands
.Pass());
31 void PostOrRunInternalGetCommandsCallback(
32 base::TaskRunner
* task_runner
,
33 const BaseSessionService::GetCommandsCallback
& callback
,
34 ScopedVector
<SessionCommand
> commands
) {
35 if (task_runner
->RunsTasksOnCurrentThread()) {
36 callback
.Run(commands
.Pass());
38 task_runner
->PostTask(FROM_HERE
,
39 base::Bind(callback
, base::Passed(&commands
)));
45 // Delay between when a command is received, and when we save it to the
47 static const int kSaveDelayMS
= 2500;
49 BaseSessionService::BaseSessionService(
51 const base::FilePath
& path
,
52 BaseSessionServiceDelegate
* delegate
)
53 : pending_reset_(false),
54 commands_since_reset_(0),
56 sequence_token_(delegate_
->GetBlockingPool()->GetSequenceToken()),
58 backend_
= new SessionBackend(type
, path
);
59 DCHECK(backend_
.get());
62 BaseSessionService::~BaseSessionService() {}
64 void BaseSessionService::MoveCurrentSessionToLastSession() {
66 RunTaskOnBackendThread(
67 FROM_HERE
, base::Bind(&SessionBackend::MoveCurrentSessionToLastSession
,
71 void BaseSessionService::DeleteLastSession() {
72 RunTaskOnBackendThread(
74 base::Bind(&SessionBackend::DeleteLastSession
, backend_
));
77 void BaseSessionService::ScheduleCommand(scoped_ptr
<SessionCommand
> command
) {
79 commands_since_reset_
++;
80 pending_commands_
.push_back(command
.release());
84 void BaseSessionService::AppendRebuildCommand(
85 scoped_ptr
<SessionCommand
> command
) {
87 pending_commands_
.push_back(command
.release());
90 void BaseSessionService::EraseCommand(SessionCommand
* old_command
) {
91 ScopedVector
<SessionCommand
>::iterator it
=
92 std::find(pending_commands_
.begin(),
93 pending_commands_
.end(),
95 CHECK(it
!= pending_commands_
.end());
96 pending_commands_
.erase(it
);
99 void BaseSessionService::SwapCommand(SessionCommand
* old_command
,
100 scoped_ptr
<SessionCommand
> new_command
) {
101 ScopedVector
<SessionCommand
>::iterator it
=
102 std::find(pending_commands_
.begin(),
103 pending_commands_
.end(),
105 CHECK(it
!= pending_commands_
.end());
106 *it
= new_command
.release();
110 void BaseSessionService::ClearPendingCommands() {
111 pending_commands_
.clear();
114 void BaseSessionService::StartSaveTimer() {
115 // Don't start a timer when testing.
116 if (delegate_
->ShouldUseDelayedSave() && base::MessageLoop::current() &&
117 !weak_factory_
.HasWeakPtrs()) {
118 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
120 base::Bind(&BaseSessionService::Save
, weak_factory_
.GetWeakPtr()),
121 base::TimeDelta::FromMilliseconds(kSaveDelayMS
));
125 void BaseSessionService::Save() {
126 // Inform the delegate that we will save the commands now, giving it the
127 // opportunity to append more commands.
128 delegate_
->OnWillSaveCommands();
130 if (pending_commands_
.empty())
133 // We create a new ScopedVector which will receive all elements from the
134 // current commands. This will also clear the current list.
135 RunTaskOnBackendThread(
137 base::Bind(&SessionBackend::AppendCommands
, backend_
,
138 base::Passed(&pending_commands_
),
141 if (pending_reset_
) {
142 commands_since_reset_
= 0;
143 pending_reset_
= false;
146 delegate_
->OnSavedCommands();
149 base::CancelableTaskTracker::TaskId
150 BaseSessionService::ScheduleGetLastSessionCommands(
151 const GetCommandsCallback
& callback
,
152 base::CancelableTaskTracker
* tracker
) {
153 base::CancelableTaskTracker::IsCanceledCallback is_canceled
;
154 base::CancelableTaskTracker::TaskId id
=
155 tracker
->NewTrackedTaskId(&is_canceled
);
157 GetCommandsCallback run_if_not_canceled
=
158 base::Bind(&RunIfNotCanceled
, is_canceled
, callback
);
160 GetCommandsCallback callback_runner
=
161 base::Bind(&PostOrRunInternalGetCommandsCallback
,
162 base::ThreadTaskRunnerHandle::Get(), run_if_not_canceled
);
164 RunTaskOnBackendThread(
166 base::Bind(&SessionBackend::ReadLastSessionCommands
, backend_
,
167 is_canceled
, callback_runner
));
171 void BaseSessionService::RunTaskOnBackendThread(
172 const tracked_objects::Location
& from_here
,
173 const base::Closure
& task
) {
174 base::SequencedWorkerPool
* pool
= delegate_
->GetBlockingPool();
175 if (!pool
->IsShutdownInProgress()) {
176 pool
->PostSequencedWorkerTask(sequence_token_
, from_here
, task
);
178 // Fall back to executing on the main thread if the sequence
179 // worker pool has been requested to shutdown (around shutdown
185 } // namespace sessions