| // Copyright 2024 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/web_state_content_download_task.h" |
| |
| #import "base/functional/bind.h" |
| #import "base/functional/callback.h" |
| #import "base/functional/callback_helpers.h" |
| #import "base/strings/sys_string_conversions.h" |
| #import "ios/web/public/web_state.h" |
| #import "net/base/net_errors.h" |
| |
| typedef void (^ProceduralBlockWithError)(NSError*); |
| |
| @interface WebStateDownloadDelegateBridge |
| : NSObject <CRWWebViewDownloadDelegate> |
| @end |
| |
| @implementation WebStateDownloadDelegateBridge { |
| base::OnceCallback<void(NSError*)> _callback; |
| } |
| |
| - (instancetype)initWithCallback:(base::OnceCallback<void(NSError*)>)callback { |
| self = [super init]; |
| if (self) { |
| _callback = std::move(callback); |
| } |
| return self; |
| } |
| - (void)downloadDidFinish { |
| std::move(_callback).Run(nil); |
| } |
| |
| - (void)downloadDidFailWithError:(NSError*)error { |
| std::move(_callback).Run(error); |
| } |
| |
| @end |
| |
| namespace web { |
| WebStateContentDownloadTask::WebStateContentDownloadTask( |
| WebState* web_state, |
| const GURL& original_url, |
| NSString* http_method, |
| const std::string& content_disposition, |
| int64_t total_bytes, |
| const std::string& mime_type, |
| NSString* identifier, |
| const scoped_refptr<base::SequencedTaskRunner>& task_runner) |
| : DownloadTaskImpl(web_state, |
| original_url, |
| http_method, |
| content_disposition, |
| total_bytes, |
| mime_type, |
| identifier, |
| task_runner) {} |
| |
| WebStateContentDownloadTask::~WebStateContentDownloadTask() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| CancelInternal(); |
| } |
| |
| void WebStateContentDownloadTask::StartInternal(const base::FilePath& path) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| auto callback = |
| base::BindOnce(&WebStateContentDownloadTask::DownloadDidFinish, |
| weak_factory_.GetWeakPtr()); |
| download_delegate_ = [[WebStateDownloadDelegateBridge alloc] |
| initWithCallback:std::move(callback)]; |
| web_state_->DownloadCurrentPage( |
| base::SysUTF8ToNSString(path.value()), download_delegate_, |
| base::CallbackToBlock( |
| base::BindOnce(&WebStateContentDownloadTask::DownloadWasCreated, |
| weak_factory_.GetWeakPtr()))); |
| } |
| |
| void WebStateContentDownloadTask::CancelInternal() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| weak_factory_.InvalidateWeakPtrs(); |
| // Client will receive status update through DownloadTask status update. |
| [download_ cancelDownload:^{ |
| }]; |
| } |
| |
| #pragma mark - Private |
| |
| void WebStateContentDownloadTask::DownloadWasCreated( |
| id<CRWWebViewDownload> download) { |
| download_ = download; |
| // Task startup is complete, trigger observers. |
| OnDownloadUpdated(); |
| } |
| |
| void WebStateContentDownloadTask::DownloadDidFinish(NSError* error) { |
| if (!error) { |
| percent_complete_ = 100; |
| received_bytes_ = total_bytes_; |
| OnDownloadFinished(DownloadResult(net::OK)); |
| } else { |
| OnDownloadFinished(DownloadResult(net::ERR_FAILED)); |
| } |
| } |
| |
| } // namespace web |