ExtensionSyncService: Properly differentiate between "pending install" and "pending...
[chromium-blink-merge.git] / components / sessions / base_session_service.cc
blobeb73b08d12b48d1e8ea9722e573523552cbc96f5
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/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 ---------------------------------------------------------
17 namespace sessions {
18 namespace {
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())
27 return;
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());
37 } else {
38 task_runner->PostTask(FROM_HERE,
39 base::Bind(callback, base::Passed(&commands)));
43 } // namespace
45 // Delay between when a command is received, and when we save it to the
46 // backend.
47 static const int kSaveDelayMS = 2500;
49 BaseSessionService::BaseSessionService(
50 SessionType type,
51 const base::FilePath& path,
52 BaseSessionServiceDelegate* delegate)
53 : pending_reset_(false),
54 commands_since_reset_(0),
55 delegate_(delegate),
56 sequence_token_(delegate_->GetBlockingPool()->GetSequenceToken()),
57 weak_factory_(this) {
58 backend_ = new SessionBackend(type, path);
59 DCHECK(backend_.get());
62 BaseSessionService::~BaseSessionService() {}
64 void BaseSessionService::MoveCurrentSessionToLastSession() {
65 Save();
66 RunTaskOnBackendThread(
67 FROM_HERE, base::Bind(&SessionBackend::MoveCurrentSessionToLastSession,
68 backend_));
71 void BaseSessionService::DeleteLastSession() {
72 RunTaskOnBackendThread(
73 FROM_HERE,
74 base::Bind(&SessionBackend::DeleteLastSession, backend_));
77 void BaseSessionService::ScheduleCommand(scoped_ptr<SessionCommand> command) {
78 DCHECK(command);
79 commands_since_reset_++;
80 pending_commands_.push_back(command.release());
81 StartSaveTimer();
84 void BaseSessionService::AppendRebuildCommand(
85 scoped_ptr<SessionCommand> command) {
86 DCHECK(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(),
94 old_command);
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(),
104 old_command);
105 CHECK(it != pending_commands_.end());
106 *it = new_command.release();
107 delete old_command;
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(
119 FROM_HERE,
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())
131 return;
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(
136 FROM_HERE,
137 base::Bind(&SessionBackend::AppendCommands, backend_,
138 base::Passed(&pending_commands_),
139 pending_reset_));
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(
165 FROM_HERE,
166 base::Bind(&SessionBackend::ReadLastSessionCommands, backend_,
167 is_canceled, callback_runner));
168 return id;
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);
177 } else {
178 // Fall back to executing on the main thread if the sequence
179 // worker pool has been requested to shutdown (around shutdown
180 // time).
181 task.Run();
185 } // namespace sessions