OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "components/sessions/base_session_service.h" | |
6 | |
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" | |
14 | |
15 // BaseSessionService --------------------------------------------------------- | |
16 | |
17 namespace sessions { | |
18 namespace { | |
19 | |
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()); | |
29 } | |
30 | |
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))); | |
40 } | |
41 } | |
42 | |
43 } // namespace | |
44 | |
45 // Delay between when a command is received, and when we save it to the | |
46 // backend. | |
47 static const int kSaveDelayMS = 2500; | |
48 | |
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()); | |
60 } | |
61 | |
62 BaseSessionService::~BaseSessionService() {} | |
63 | |
64 void BaseSessionService::MoveCurrentSessionToLastSession() { | |
65 Save(); | |
66 RunTaskOnBackendThread( | |
67 FROM_HERE, base::Bind(&SessionBackend::MoveCurrentSessionToLastSession, | |
68 backend_)); | |
69 } | |
70 | |
71 void BaseSessionService::DeleteLastSession() { | |
72 RunTaskOnBackendThread( | |
73 FROM_HERE, | |
74 base::Bind(&SessionBackend::DeleteLastSession, backend_)); | |
75 } | |
76 | |
77 void BaseSessionService::ScheduleCommand(scoped_ptr<SessionCommand> command) { | |
78 DCHECK(command); | |
79 commands_since_reset_++; | |
80 pending_commands_.push_back(command.release()); | |
81 StartSaveTimer(); | |
82 } | |
83 | |
84 void BaseSessionService::AppendRebuildCommand( | |
85 scoped_ptr<SessionCommand> command) { | |
86 DCHECK(command); | |
87 pending_commands_.push_back(command.release()); | |
88 } | |
89 | |
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); | |
97 } | |
98 | |
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; | |
108 } | |
109 | |
110 void BaseSessionService::ClearPendingCommands() { | |
111 pending_commands_.clear(); | |
112 } | |
113 | |
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)); | |
122 } | |
123 } | |
124 | |
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(); | |
129 | |
130 if (pending_commands_.empty()) | |
131 return; | |
132 | |
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_)); | |
140 | |
141 if (pending_reset_) { | |
142 commands_since_reset_ = 0; | |
143 pending_reset_ = false; | |
144 } | |
145 | |
146 delegate_->OnSavedCommands(); | |
147 } | |
148 | |
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); | |
156 | |
157 GetCommandsCallback run_if_not_canceled = | |
158 base::Bind(&RunIfNotCanceled, is_canceled, callback); | |
159 | |
160 GetCommandsCallback callback_runner = | |
161 base::Bind(&PostOrRunInternalGetCommandsCallback, | |
162 base::ThreadTaskRunnerHandle::Get(), run_if_not_canceled); | |
163 | |
164 RunTaskOnBackendThread( | |
165 FROM_HERE, | |
166 base::Bind(&SessionBackend::ReadLastSessionCommands, backend_, | |
167 is_canceled, callback_runner)); | |
168 return id; | |
169 } | |
170 | |
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(); | |
182 } | |
183 } | |
184 | |
185 } // namespace sessions | |
OLD | NEW |