| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 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/download/internal/controller_impl.h" |
| 6 |
| 7 #include <string> |
| 8 #include <vector> |
| 9 |
| 10 #include "base/bind.h" |
| 11 #include "base/threading/thread_task_runner_handle.h" |
| 12 #include "components/download/internal/client_set.h" |
| 13 #include "components/download/internal/config.h" |
| 14 #include "components/download/internal/entry.h" |
| 15 #include "components/download/internal/entry_utils.h" |
| 16 #include "components/download/internal/model.h" |
| 17 #include "components/download/internal/stats.h" |
| 18 |
| 19 namespace download { |
| 20 |
| 21 ControllerImpl::ControllerImpl(std::unique_ptr<ClientSet> clients, |
| 22 std::unique_ptr<Configuration> config, |
| 23 std::unique_ptr<DownloadDriver> driver, |
| 24 std::unique_ptr<Model> model) |
| 25 : clients_(std::move(clients)), |
| 26 config_(std::move(config)), |
| 27 driver_(std::move(driver)), |
| 28 model_(std::move(model)) {} |
| 29 |
| 30 ControllerImpl::~ControllerImpl() = default; |
| 31 |
| 32 void ControllerImpl::Initialize() { |
| 33 DCHECK(!startup_status_.Complete()); |
| 34 |
| 35 driver_->Initialize(this); |
| 36 model_->Initialize(this); |
| 37 } |
| 38 |
| 39 const StartupStatus& ControllerImpl::GetStartupStatus() { |
| 40 return startup_status_; |
| 41 } |
| 42 |
| 43 void ControllerImpl::StartDownload(const DownloadParams& params) { |
| 44 DCHECK(startup_status_.Ok()); |
| 45 |
| 46 if (start_callbacks_.find(params.guid) != start_callbacks_.end() || |
| 47 model_->Get(params.guid) != nullptr) { |
| 48 HandleStartDownloadResponse(params.client, params.guid, |
| 49 DownloadParams::StartResult::UNEXPECTED_GUID, |
| 50 params.callback); |
| 51 return; |
| 52 } |
| 53 |
| 54 auto* client = clients_->GetClient(params.client); |
| 55 if (!client) { |
| 56 HandleStartDownloadResponse(params.client, params.guid, |
| 57 DownloadParams::StartResult::UNEXPECTED_CLIENT, |
| 58 params.callback); |
| 59 return; |
| 60 } |
| 61 |
| 62 uint32_t client_count = |
| 63 util::GetNumberOfEntriesForClient(params.client, model_->PeekEntries()); |
| 64 if (client_count >= config_->max_scheduled_downloads) { |
| 65 HandleStartDownloadResponse(params.client, params.guid, |
| 66 DownloadParams::StartResult::BACKOFF, |
| 67 params.callback); |
| 68 return; |
| 69 } |
| 70 |
| 71 start_callbacks_[params.guid] = params.callback; |
| 72 model_->Add(Entry(params)); |
| 73 } |
| 74 |
| 75 void ControllerImpl::PauseDownload(const std::string& guid) { |
| 76 DCHECK(startup_status_.Ok()); |
| 77 |
| 78 auto* entry = model_->Get(guid); |
| 79 DCHECK(entry); |
| 80 |
| 81 if (entry->state == Entry::State::PAUSED || |
| 82 entry->state == Entry::State::COMPLETE || |
| 83 entry->state == Entry::State::WATCHDOG) { |
| 84 return; |
| 85 } |
| 86 |
| 87 // TODO(dtrainor): Pause the download. |
| 88 } |
| 89 |
| 90 void ControllerImpl::ResumeDownload(const std::string& guid) { |
| 91 DCHECK(startup_status_.Ok()); |
| 92 |
| 93 auto* entry = model_->Get(guid); |
| 94 DCHECK(entry); |
| 95 |
| 96 if (entry->state != Entry::State::PAUSED) |
| 97 return; |
| 98 |
| 99 // TODO(dtrainor): Resume the download. |
| 100 } |
| 101 |
| 102 void ControllerImpl::CancelDownload(const std::string& guid) { |
| 103 DCHECK(startup_status_.Ok()); |
| 104 |
| 105 auto* entry = model_->Get(guid); |
| 106 DCHECK(entry); |
| 107 |
| 108 if (entry->state == Entry::State::NEW) { |
| 109 // Check if we're currently trying to add the download. |
| 110 DCHECK(start_callbacks_.find(entry->guid) != start_callbacks_.end()); |
| 111 HandleStartDownloadResponse(entry->client, entry->guid, |
| 112 DownloadParams::StartResult::CLIENT_CANCELLED); |
| 113 } |
| 114 |
| 115 // TODO(dtrainor): Cancel the download. |
| 116 } |
| 117 |
| 118 void ControllerImpl::ChangeDownloadCriteria(const std::string& guid, |
| 119 const SchedulingParams& params) { |
| 120 DCHECK(startup_status_.Ok()); |
| 121 |
| 122 auto* entry = model_->Get(guid); |
| 123 DCHECK(entry); |
| 124 |
| 125 // TODO(dtrainor): Change the criteria of the download. |
| 126 } |
| 127 |
| 128 DownloadClient ControllerImpl::GetOwnerOfDownload(const std::string& guid) { |
| 129 auto* entry = model_->Get(guid); |
| 130 return entry ? entry->client : DownloadClient::INVALID; |
| 131 } |
| 132 |
| 133 void ControllerImpl::OnDriverReady(bool success) { |
| 134 DCHECK(!startup_status_.driver_ok.has_value()); |
| 135 startup_status_.driver_ok = success; |
| 136 AttemptToFinalizeSetup(); |
| 137 } |
| 138 |
| 139 void ControllerImpl::OnDownloadCreated(const DriverEntry& download) {} |
| 140 |
| 141 void ControllerImpl::OnDownloadFailed(const DriverEntry& download, int reason) { |
| 142 } |
| 143 |
| 144 void ControllerImpl::OnDownloadSucceeded(const DriverEntry& download, |
| 145 const base::FilePath& path) {} |
| 146 |
| 147 void ControllerImpl::OnDownloadUpdated(const DriverEntry& download) {} |
| 148 |
| 149 void ControllerImpl::OnModelReady(bool success) { |
| 150 DCHECK(!startup_status_.model_ok.has_value()); |
| 151 startup_status_.model_ok = success; |
| 152 AttemptToFinalizeSetup(); |
| 153 } |
| 154 |
| 155 void ControllerImpl::OnItemAdded(bool success, |
| 156 DownloadClient client, |
| 157 const std::string& guid) { |
| 158 // If the StartCallback doesn't exist, we already notified the Client about |
| 159 // this item. That means something went wrong, so stop here. |
| 160 if (start_callbacks_.find(guid) == start_callbacks_.end()) |
| 161 return; |
| 162 |
| 163 if (!success) { |
| 164 HandleStartDownloadResponse(client, guid, |
| 165 DownloadParams::StartResult::INTERNAL_ERROR); |
| 166 return; |
| 167 } |
| 168 |
| 169 HandleStartDownloadResponse(client, guid, |
| 170 DownloadParams::StartResult::ACCEPTED); |
| 171 |
| 172 auto* entry = model_->Get(guid); |
| 173 DCHECK(entry); |
| 174 DCHECK_EQ(Entry::State::NEW, entry->state); |
| 175 |
| 176 // TODO(dtrainor): Make sure we're running all of the downloads we care about. |
| 177 } |
| 178 |
| 179 void ControllerImpl::OnItemUpdated(bool success, |
| 180 DownloadClient client, |
| 181 const std::string& guid) { |
| 182 // TODO(dtrainor): Fail and clean up the download if necessary. |
| 183 } |
| 184 |
| 185 void ControllerImpl::OnItemRemoved(bool success, |
| 186 DownloadClient client, |
| 187 const std::string& guid) { |
| 188 // TODO(dtrainor): Fail and clean up the download if necessary. |
| 189 } |
| 190 |
| 191 void ControllerImpl::AttemptToFinalizeSetup() { |
| 192 if (!startup_status_.Complete()) |
| 193 return; |
| 194 |
| 195 stats::LogControllerStartupStatus(startup_status_); |
| 196 if (!startup_status_.Ok()) { |
| 197 // TODO(dtrainor): Recover here. Try to clean up any disk state and, if |
| 198 // possible, any DownloadDriver data and continue with initialization? |
| 199 return; |
| 200 } |
| 201 |
| 202 CancelOrphanedRequests(); |
| 203 ResolveInitialRequestStates(); |
| 204 PullCurrentRequestStatus(); |
| 205 |
| 206 // TODO(dtrainor): Post this so that the initialization step is finalized |
| 207 // before Clients can take action. |
| 208 NotifyClientsOfStartup(); |
| 209 } |
| 210 |
| 211 void ControllerImpl::CancelOrphanedRequests() { |
| 212 auto entries = model_->PeekEntries(); |
| 213 |
| 214 std::vector<std::string> guids_to_remove; |
| 215 for (auto* entry : entries) { |
| 216 if (!clients_->GetClient(entry->client)) |
| 217 guids_to_remove.push_back(entry->guid); |
| 218 } |
| 219 |
| 220 for (auto guid : guids_to_remove) { |
| 221 // TODO(dtrainor): Remove the download. |
| 222 } |
| 223 } |
| 224 |
| 225 void ControllerImpl::ResolveInitialRequestStates() { |
| 226 // TODO(dtrainor): Implement. |
| 227 } |
| 228 |
| 229 void ControllerImpl::PullCurrentRequestStatus() { |
| 230 // TODO(dtrainor): Implement. |
| 231 } |
| 232 |
| 233 void ControllerImpl::NotifyClientsOfStartup() { |
| 234 auto categorized = util::MapEntriesToClients(clients_->GetRegisteredClients(), |
| 235 model_->PeekEntries()); |
| 236 |
| 237 for (auto client_id : clients_->GetRegisteredClients()) { |
| 238 clients_->GetClient(client_id)->OnServiceInitialized( |
| 239 categorized[client_id]); |
| 240 } |
| 241 } |
| 242 |
| 243 void ControllerImpl::HandleStartDownloadResponse( |
| 244 DownloadClient client, |
| 245 const std::string& guid, |
| 246 DownloadParams::StartResult result) { |
| 247 auto callback = start_callbacks_[guid]; |
| 248 start_callbacks_.erase(guid); |
| 249 HandleStartDownloadResponse(client, guid, result, callback); |
| 250 } |
| 251 |
| 252 void ControllerImpl::HandleStartDownloadResponse( |
| 253 DownloadClient client, |
| 254 const std::string& guid, |
| 255 DownloadParams::StartResult result, |
| 256 const DownloadParams::StartCallback& callback) { |
| 257 stats::LogStartDownloadResult(client, result); |
| 258 |
| 259 if (result != DownloadParams::StartResult::ACCEPTED) { |
| 260 // TODO(dtrainor): Clean up any download state. |
| 261 } |
| 262 |
| 263 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 264 FROM_HERE, base::Bind(callback, guid, result)); |
| 265 } |
| 266 |
| 267 } // namespace download |
| OLD | NEW |