blob: ba33cec4a64ff7d0daaeb1a21f2afe1846311cc6 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/web/download/download_controller_impl.h"
#import "base/strings/sys_string_conversions.h"
#import "base/task/sequenced_task_runner.h"
#import "base/task/task_traits.h"
#import "base/task/thread_pool.h"
#import "ios/web/download/download_native_task_bridge.h"
#import "ios/web/download/download_native_task_impl.h"
#import "ios/web/download/web_state_content_download_task.h"
#import "ios/web/public/browser_state.h"
#import "ios/web/public/download/download_controller_delegate.h"
#import "ios/web/public/web_state.h"
#import "net/base/apple/url_conversions.h"
#import "net/http/http_request_headers.h"
namespace {
const char kDownloadControllerKey = 0;
} // namespace
namespace web {
// static
DownloadController* DownloadController::FromBrowserState(
BrowserState* browser_state) {
DCHECK(browser_state);
if (!browser_state->GetUserData(&kDownloadControllerKey)) {
browser_state->SetUserData(&kDownloadControllerKey,
std::make_unique<DownloadControllerImpl>());
}
return static_cast<DownloadControllerImpl*>(
browser_state->GetUserData(&kDownloadControllerKey));
}
DownloadControllerImpl::DownloadControllerImpl()
: task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::USER_BLOCKING})) {}
DownloadControllerImpl::~DownloadControllerImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (DownloadTask* task : alive_tasks_) {
task->RemoveObserver(this);
task->Cancel();
}
if (delegate_)
delegate_->OnDownloadControllerDestroyed(this);
DCHECK(!delegate_);
}
void DownloadControllerImpl::CreateWebStateDownloadTask(WebState* web_state,
NSString* identifier,
int64_t total_bytes) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!delegate_) {
return;
}
OnDownloadCreated(std::make_unique<WebStateContentDownloadTask>(
web_state, web_state->GetLastCommittedURL(), @"", "", total_bytes,
web_state->GetContentsMimeType(), identifier, task_runner_));
}
void DownloadControllerImpl::CreateNativeDownloadTask(
WebState* web_state,
NSString* identifier,
const GURL& original_url,
NSString* http_method,
const std::string& content_disposition,
int64_t total_bytes,
const std::string& mime_type,
DownloadNativeTaskBridge* download) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!delegate_) {
[download cancel];
return;
}
OnDownloadCreated(std::make_unique<DownloadNativeTaskImpl>(
web_state, original_url, http_method, content_disposition, total_bytes,
mime_type, identifier, task_runner_, download));
}
void DownloadControllerImpl::SetDelegate(DownloadControllerDelegate* delegate) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
delegate_ = delegate;
}
DownloadControllerDelegate* DownloadControllerImpl::GetDelegate() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return delegate_;
}
void DownloadControllerImpl::OnDownloadDestroyed(DownloadTask* task) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = alive_tasks_.find(task);
DCHECK(it != alive_tasks_.end());
task->RemoveObserver(this);
alive_tasks_.erase(it);
}
void DownloadControllerImpl::OnDownloadCreated(
std::unique_ptr<DownloadTaskImpl> task) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(task);
alive_tasks_.insert(task.get());
task->AddObserver(this);
DCHECK(task->GetWebState());
WebState* web_state = task->GetWebState();
delegate_->OnDownloadCreated(this, web_state, std::move(task));
}
} // namespace web