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/threading/thread.h"
9 #include "components/sessions/base_session_service_delegate.h"
10 #include "components/sessions/session_backend.h"
12 // BaseSessionService ---------------------------------------------------------
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())
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());
35 task_runner
->PostTask(FROM_HERE
,
36 base::Bind(callback
, base::Passed(&commands
)));
42 // Delay between when a command is received, and when we save it to the
44 static const int kSaveDelayMS
= 2500;
46 BaseSessionService::BaseSessionService(
48 const base::FilePath
& path
,
49 BaseSessionServiceDelegate
* delegate
)
50 : pending_reset_(false),
51 commands_since_reset_(0),
53 sequence_token_(delegate_
->GetBlockingPool()->GetSequenceToken()),
55 backend_
= new SessionBackend(type
, path
);
56 DCHECK(backend_
.get());
59 BaseSessionService::~BaseSessionService() {}
61 void BaseSessionService::MoveCurrentSessionToLastSession() {
63 RunTaskOnBackendThread(
64 FROM_HERE
, base::Bind(&SessionBackend::MoveCurrentSessionToLastSession
,
68 void BaseSessionService::DeleteLastSession() {
69 RunTaskOnBackendThread(
71 base::Bind(&SessionBackend::DeleteLastSession
, backend_
));
74 void BaseSessionService::ScheduleCommand(scoped_ptr
<SessionCommand
> command
) {
76 commands_since_reset_
++;
77 pending_commands_
.push_back(command
.release());
81 void BaseSessionService::AppendRebuildCommand(
82 scoped_ptr
<SessionCommand
> 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(),
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(),
102 CHECK(it
!= pending_commands_
.end());
103 *it
= new_command
.release();
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(
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())
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(
135 base::Bind(&SessionBackend::AppendCommands
, backend_
,
136 base::Passed(&pending_commands_
),
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(
164 base::Bind(&SessionBackend::ReadLastSessionCommands
, backend_
,
165 is_canceled
, callback_runner
));
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
);
176 // Fall back to executing on the main thread if the sequence
177 // worker pool has been requested to shutdown (around shutdown
183 } // namespace sessions