| 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 |