blob: 1b96430ec00769bf5c419380b2f714f4ff3a1ce0 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/background_fetch/background_fetch_scheduler.h"
#include "base/guid.h"
#include "content/browser/background_fetch/background_fetch_job_controller.h"
namespace content {
BackgroundFetchScheduler::Controller::Controller(
const BackgroundFetchRegistrationId& registration_id,
FinishedCallback finished_callback)
: registration_id_(registration_id),
finished_callback_(std::move(finished_callback)) {
DCHECK(finished_callback_);
}
BackgroundFetchScheduler::Controller::~Controller() = default;
void BackgroundFetchScheduler::Controller::Finish(bool abort) {
DCHECK(abort || !HasMoreRequests());
std::move(finished_callback_).Run(registration_id_, abort);
}
BackgroundFetchScheduler::BackgroundFetchScheduler(
BackgroundFetchScheduler::RequestProvider* request_provider)
: request_provider_(request_provider) {}
BackgroundFetchScheduler::~BackgroundFetchScheduler() = default;
void BackgroundFetchScheduler::AddJobController(
BackgroundFetchScheduler::Controller* controller) {
controller_queue_.push_back(controller);
while (!controller_queue_.empty() &&
download_controller_map_.size() < max_concurrent_downloads_) {
ScheduleDownload();
}
}
void BackgroundFetchScheduler::ScheduleDownload() {
DCHECK(download_controller_map_.size() < max_concurrent_downloads_);
if (controller_queue_.empty())
return;
auto* controller = controller_queue_.front();
controller_queue_.pop_front();
request_provider_->PopNextRequest(
controller->registration_id(),
base::BindOnce(&BackgroundFetchScheduler::DidPopNextRequest,
base::Unretained(this), controller));
}
void BackgroundFetchScheduler::DidPopNextRequest(
BackgroundFetchScheduler::Controller* controller,
scoped_refptr<BackgroundFetchRequestInfo> request_info) {
download_controller_map_[request_info->download_guid()] = controller;
controller->StartRequest(request_info);
}
void BackgroundFetchScheduler::MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request) {
DCHECK(download_controller_map_.count(request->download_guid()));
auto* controller = download_controller_map_[request->download_guid()];
download_controller_map_.erase(request->download_guid());
request_provider_->MarkRequestAsComplete(
controller->registration_id(), request.get(),
base::BindOnce(&BackgroundFetchScheduler::DidMarkRequestAsComplete,
base::Unretained(this), controller));
}
void BackgroundFetchScheduler::DidMarkRequestAsComplete(
BackgroundFetchScheduler::Controller* controller) {
if (controller->HasMoreRequests())
controller_queue_.push_back(controller);
else
controller->Finish(false);
ScheduleDownload();
}
void BackgroundFetchScheduler::OnJobAborted(
const BackgroundFetchRegistrationId& registration_id,
std::vector<std::string> aborted_guids) {
// For every active download that was aborted, remove it and schedule a new
// download.
for (const auto& guid : aborted_guids) {
download_controller_map_.erase(guid);
ScheduleDownload();
}
}
} // namespace content