diff --git a/components/ipfs/BUILD.gn b/components/ipfs/BUILD.gn index 657bf4311dc4..c69ba6f124f2 100644 --- a/components/ipfs/BUILD.gn +++ b/components/ipfs/BUILD.gn @@ -10,16 +10,10 @@ source_set("ipfs") { "features.h", "import/imported_data.cc", "import/imported_data.h", - "import/ipfs_directory_import_worker.cc", - "import/ipfs_directory_import_worker.h", - "import/ipfs_file_import_worker.cc", - "import/ipfs_file_import_worker.h", "import/ipfs_import_worker_base.cc", "import/ipfs_import_worker_base.h", "import/ipfs_link_import_worker.cc", "import/ipfs_link_import_worker.h", - "import/ipfs_text_import_worker.cc", - "import/ipfs_text_import_worker.h", "ipfs_constants.cc", "ipfs_constants.h", "ipfs_interstitial_controller_client.cc", diff --git a/components/ipfs/import/ipfs_directory_import_worker.cc b/components/ipfs/import/ipfs_directory_import_worker.cc deleted file mode 100644 index c99a4f21af9e..000000000000 --- a/components/ipfs/import/ipfs_directory_import_worker.cc +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright (c) 2021 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "brave/components/ipfs/import/ipfs_directory_import_worker.h" - -#include -#include -#include -#include - -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "base/guid.h" -#include "base/task/post_task.h" -#include "base/task/thread_pool.h" -#include "base/task_runner_util.h" -#include "brave/components/ipfs/ipfs_constants.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "net/base/mime_util.h" -#include "services/network/public/cpp/simple_url_loader.h" - -namespace { - -const char kDirectoryMimeType[] = "application/x-directory"; - -bool GetRelativePathComponent(const base::FilePath& parent, - const base::FilePath& child, - base::FilePath::StringType* out) { - if (!parent.IsParent(child)) - return false; - - std::vector parent_components; - std::vector child_components; - parent.GetComponents(&parent_components); - child.GetComponents(&child_components); - - size_t i = 0; - while (i < parent_components.size() && - child_components[i] == parent_components[i]) { - ++i; - } - - while (i < child_components.size()) { - out->append(child_components[i]); - if (++i < child_components.size()) - out->append(FILE_PATH_LITERAL("/")); - } - return true; -} - -std::vector EnumberateDirectoryFiles( - base::FilePath dir_path) { - std::vector files; - base::FileEnumerator file_enum( - dir_path, true, - base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); - for (base::FilePath enum_path = file_enum.Next(); !enum_path.empty(); - enum_path = file_enum.Next()) { - // Skip symlinks. - if (base::IsLink(enum_path)) - continue; - files.push_back(ipfs::ImportFileInfo(enum_path, file_enum.GetInfo())); - } - - return files; -} - -std::unique_ptr BuildBlobWithFolder( - base::FilePath upload_path, - std::string mime_boundary, - std::vector files) { - auto blob_builder = - std::make_unique(base::GenerateGUID()); - for (const auto& info : files) { - std::string data_header; - base::FilePath::StringType relative_path; - GetRelativePathComponent(upload_path, info.path, &relative_path); - - std::string mime_type = - info.info.IsDirectory() ? kDirectoryMimeType : ipfs::kFileMimeType; - data_header.append("\r\n"); - ipfs::AddMultipartHeaderForUploadWithFileName( - ipfs::kFileValueName, base::FilePath(relative_path).MaybeAsASCII(), - info.path.MaybeAsASCII(), mime_boundary, mime_type, &data_header); - blob_builder->AppendData(data_header); - if (mime_type == ipfs::kFileMimeType) { - blob_builder->AppendFile(info.path, 0, info.info.GetSize(), base::Time()); - } - } - - std::string post_data_footer = "\r\n"; - net::AddMultipartFinalDelimiterForUpload(mime_boundary, &post_data_footer); - blob_builder->AppendData(post_data_footer); - - return blob_builder; -} - -} // namespace - -namespace ipfs { - -IpfsDirectoryImportWorker::IpfsDirectoryImportWorker( - content::BrowserContext* context, - const GURL& endpoint, - ImportCompletedCallback callback, - const base::FilePath& source_path, - const std::string& key) - : IpfsImportWorkerBase(context, endpoint, std::move(callback), key), - source_path_(source_path), - file_task_runner_(base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), - weak_factory_(this) { - std::string mime_boundary = net::GenerateMimeMultipartBoundary(); - auto blob_builder = - std::make_unique(base::GenerateGUID()); - - base::PostTaskAndReplyWithResult( - file_task_runner_.get(), FROM_HERE, - base::BindOnce(&EnumberateDirectoryFiles, source_path_), - base::BindOnce(&IpfsDirectoryImportWorker::CreateRequestWithFolder, - weak_factory_.GetWeakPtr(), mime_boundary)); -} - -IpfsDirectoryImportWorker::~IpfsDirectoryImportWorker() = default; - -void IpfsDirectoryImportWorker::CreateRequestWithFolder( - const std::string& mime_boundary, - std::vector files) { - auto blob_builder_callback = - base::BindOnce(&BuildBlobWithFolder, source_path_.DirName(), - mime_boundary, std::move(files)); - - std::string content_type = kIPFSImportMultipartContentType; - content_type += " boundary="; - content_type += mime_boundary; - StartImport(std::move(blob_builder_callback), content_type, - source_path_.BaseName().MaybeAsASCII()); -} - -} // namespace ipfs diff --git a/components/ipfs/import/ipfs_directory_import_worker.h b/components/ipfs/import/ipfs_directory_import_worker.h deleted file mode 100644 index 772f172b800e..000000000000 --- a/components/ipfs/import/ipfs_directory_import_worker.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (c) 2021 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_DIRECTORY_IMPORT_WORKER_H_ -#define BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_DIRECTORY_IMPORT_WORKER_H_ - -#include -#include -#include -#include - -#include "base/callback.h" -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "base/memory/scoped_refptr.h" -#include "brave/components/ipfs/import/imported_data.h" -#include "brave/components/ipfs/import/ipfs_import_worker_base.h" -#include "url/gurl.h" - -namespace ipfs { - -struct ImportFileInfo { - ImportFileInfo(base::FilePath full_path, - base::FileEnumerator::FileInfo information) { - path = full_path; - info = information; - } - base::FilePath path; - base::FileEnumerator::FileInfo info; -}; - -class IpfsDirectoryImportWorker : public IpfsImportWorkerBase { - public: - IpfsDirectoryImportWorker(content::BrowserContext* context, - const GURL& endpoint, - ImportCompletedCallback callback, - const base::FilePath& path, - const std::string& key); - ~IpfsDirectoryImportWorker() override; - - IpfsDirectoryImportWorker(const IpfsDirectoryImportWorker&) = delete; - IpfsDirectoryImportWorker& operator=(const IpfsDirectoryImportWorker&) = - delete; - - private: - void OnImportDataAvailable(const base::FilePath path); - - void CreateRequestWithFolder(const std::string& mime_boundary, - std::vector files); - void OnImportAddComplete(std::unique_ptr response_body); - - base::FilePath source_path_; - std::unique_ptr url_loader_; - scoped_refptr file_task_runner_; - base::WeakPtrFactory weak_factory_; -}; - -} // namespace ipfs - -#endif // BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_DIRECTORY_IMPORT_WORKER_H_ diff --git a/components/ipfs/import/ipfs_file_import_worker.cc b/components/ipfs/import/ipfs_file_import_worker.cc deleted file mode 100644 index 6dfce3fd3abe..000000000000 --- a/components/ipfs/import/ipfs_file_import_worker.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2021 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "brave/components/ipfs/import/ipfs_file_import_worker.h" - -#include - -#include "base/files/file_util.h" -#include "base/guid.h" -#include "base/task/post_task.h" -#include "base/task/thread_pool.h" -#include "base/task_runner_util.h" -#include "brave/components/ipfs/ipfs_constants.h" -#include "brave/components/ipfs/ipfs_network_utils.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "storage/browser/blob/blob_data_builder.h" -#include "url/gurl.h" - -namespace ipfs { - -IpfsFileImportWorker::IpfsFileImportWorker(content::BrowserContext* context, - const GURL& endpoint, - ImportCompletedCallback callback, - const base::FilePath& path, - const std::string& key) - : IpfsImportWorkerBase(context, endpoint, std::move(callback), key), - weak_factory_(this) { - std::string filename = path.BaseName().MaybeAsASCII(); - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::MayBlock()}, base::BindOnce(&CalculateFileSize, path), - base::BindOnce(&IpfsFileImportWorker::CreateRequestWithFile, - weak_factory_.GetWeakPtr(), path, kFileMimeType, - filename)); -} - -IpfsFileImportWorker::~IpfsFileImportWorker() = default; - -} // namespace ipfs diff --git a/components/ipfs/import/ipfs_file_import_worker.h b/components/ipfs/import/ipfs_file_import_worker.h deleted file mode 100644 index cc67df51abbf..000000000000 --- a/components/ipfs/import/ipfs_file_import_worker.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2021 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_FILE_IMPORT_WORKER_H_ -#define BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_FILE_IMPORT_WORKER_H_ - -#include -#include -#include - -#include "base/callback.h" -#include "brave/components/ipfs/import/imported_data.h" -#include "brave/components/ipfs/import/ipfs_import_worker_base.h" -#include "url/gurl.h" - -namespace ipfs { - -class IpfsFileImportWorker : public IpfsImportWorkerBase { - public: - IpfsFileImportWorker(content::BrowserContext* context, - const GURL& endpoint, - ImportCompletedCallback callback, - const base::FilePath& path, - const std::string& key); - ~IpfsFileImportWorker() override; - - IpfsFileImportWorker(const IpfsFileImportWorker&) = delete; - IpfsFileImportWorker& operator=(const IpfsFileImportWorker&) = delete; - - private: - base::WeakPtrFactory weak_factory_; -}; - -} // namespace ipfs - -#endif // BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_FILE_IMPORT_WORKER_H_ diff --git a/components/ipfs/import/ipfs_import_worker_base.cc b/components/ipfs/import/ipfs_import_worker_base.cc index 7be1a6cb0c0d..b8f7be37f81d 100644 --- a/components/ipfs/import/ipfs_import_worker_base.cc +++ b/components/ipfs/import/ipfs_import_worker_base.cc @@ -14,6 +14,7 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "base/task_runner_util.h" #include "base/time/time.h" #include "brave/components/ipfs/ipfs_constants.h" @@ -66,10 +67,6 @@ IpfsImportWorkerBase::IpfsImportWorkerBase(content::BrowserContext* context, server_endpoint_(endpoint), key_to_publish_(key), browser_context_(context), - io_task_runner_(base::CreateSequencedTaskRunner( - {base::MayBlock(), content::BrowserThread::IO, - base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), weak_factory_(this) { DCHECK(context); DCHECK(endpoint.is_valid()); @@ -81,73 +78,60 @@ IpfsImportWorkerBase::IpfsImportWorkerBase(content::BrowserContext* context, IpfsImportWorkerBase::~IpfsImportWorkerBase() = default; -void IpfsImportWorkerBase::CreateRequestWithFile( - const base::FilePath upload_file_path, - const std::string& mime_type, - const std::string& filename, - int64_t file_size) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - std::string mime_boundary = net::GenerateMimeMultipartBoundary(); - auto blob_builder_callback = - base::BindOnce(&BuildBlobWithFile, upload_file_path, file_size, mime_type, - filename, mime_boundary); - std::string content_type = kIPFSImportMultipartContentType; - content_type += " boundary="; - content_type += mime_boundary; - StartImport(std::move(blob_builder_callback), content_type, filename); +void IpfsImportWorkerBase::ImportFile(const base::FilePath path) { + ImportFile(path, kFileMimeType, path.BaseName().MaybeAsASCII()); } -void IpfsImportWorkerBase::StartImport( - BlobBuilderCallback blob_builder_callback, - const std::string& content_type, - const std::string& filename) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +void IpfsImportWorkerBase::ImportFile(const base::FilePath upload_file_path, + const std::string& mime_type, + const std::string& filename) { data_->filename = filename; + auto blob_storage_getter = + content::BrowserContext::GetBlobStorageContext(browser_context_); + + auto upload_callback = base::BindOnce(&IpfsImportWorkerBase::UploadData, + weak_factory_.GetWeakPtr()); + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&ipfs::CalculateFileSize, upload_file_path), + base::BindOnce(&CreateRequestForFile, upload_file_path, + std::move(blob_storage_getter), mime_type, filename, + std::move(upload_callback))); +} + +void IpfsImportWorkerBase::ImportFolder(const base::FilePath folder_path) { auto blob_storage_context_getter = content::BrowserContext::GetBlobStorageContext(browser_context_); - base::PostTaskAndReplyWithResult( - io_task_runner_.get(), FROM_HERE, - base::BindOnce(&IpfsImportWorkerBase::CreateResourceRequest, - base::Unretained(this), std::move(blob_builder_callback), - content_type, std::move(blob_storage_context_getter)), - base::BindOnce(&IpfsImportWorkerBase::UploadDataUI, - weak_factory_.GetWeakPtr())); + + auto upload_callback = base::BindOnce(&IpfsImportWorkerBase::UploadData, + weak_factory_.GetWeakPtr()); + data_->filename = folder_path.BaseName().MaybeAsASCII(); + CreateRequestForFolder(folder_path, std::move(blob_storage_context_getter), + std::move(upload_callback)); } -std::unique_ptr -IpfsImportWorkerBase::CreateResourceRequest( - BlobBuilderCallback blob_builder_callback, - const std::string& content_type, - content::BrowserContext::BlobContextGetter storage_context_getter) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - std::unique_ptr blob_builder = - std::move(blob_builder_callback).Run(); - - auto storage_context = std::move(storage_context_getter).Run(); - std::unique_ptr blob_handle = - storage_context->AddFinishedBlob(std::move(blob_builder)); - - auto blob = blink::mojom::SerializedBlob::New(); - blob->uuid = blob_handle->uuid(); - blob->size = blob_handle->size(); - storage::BlobImpl::Create( - std::make_unique(*blob_handle), - blob->blob.InitWithNewPipeAndPassReceiver()); - // Use a Data Pipe to transfer the blob. - mojo::PendingRemote data_pipe_getter_remote; - mojo::Remote blob_remote(std::move(blob->blob)); - blob_remote->AsDataPipeGetter( - data_pipe_getter_remote.InitWithNewPipeAndPassReceiver()); - - auto request = std::make_unique(); - request->request_body = new network::ResourceRequestBody(); - request->request_body->AppendDataPipe(std::move(data_pipe_getter_remote)); - request->headers.SetHeader(net::HttpRequestHeaders::kContentType, - content_type); - return request; +void IpfsImportWorkerBase::ImportText(const std::string& text, + const std::string& host) { + if (text.empty() || host.empty()) { + NotifyImportCompleted(IPFS_IMPORT_ERROR_REQUEST_EMPTY); + return; + } + size_t key = base::FastHash(base::as_bytes(base::make_span(text))); + std::string filename = host; + filename += "_"; + filename += std::to_string(key); + auto blob_storage_context_getter = + content::BrowserContext::GetBlobStorageContext(browser_context_); + + auto upload_callback = base::BindOnce(&IpfsImportWorkerBase::UploadData, + weak_factory_.GetWeakPtr()); + data_->filename = filename; + CreateRequestForText(text, filename, std::move(blob_storage_context_getter), + std::move(upload_callback)); } -void IpfsImportWorkerBase::UploadDataUI( +void IpfsImportWorkerBase::UploadData( std::unique_ptr request) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!request) @@ -323,4 +307,5 @@ scoped_refptr IpfsImportWorkerBase::GetUrlLoaderFactory() { return url_loader_factory_; } + } // namespace ipfs diff --git a/components/ipfs/import/ipfs_import_worker_base.h b/components/ipfs/import/ipfs_import_worker_base.h index 6ce0bef3fe66..7a17d0e9b638 100644 --- a/components/ipfs/import/ipfs_import_worker_base.h +++ b/components/ipfs/import/ipfs_import_worker_base.h @@ -59,26 +59,20 @@ class IpfsImportWorkerBase { IpfsImportWorkerBase(const IpfsImportWorkerBase&) = delete; IpfsImportWorkerBase& operator=(const IpfsImportWorkerBase&) = delete; + void ImportFile(const base::FilePath upload_file_path); + void ImportFile(const base::FilePath upload_file_path, + const std::string& mime_type, + const std::string& filename); + void ImportText(const std::string& text, const std::string& host); + void ImportFolder(const base::FilePath folder_path); + protected: - void StartImport(BlobBuilderCallback blob_builder_callback, - const std::string& content_type, - const std::string& filename); scoped_refptr GetUrlLoaderFactory(); virtual void NotifyImportCompleted(ipfs::ImportState state); - void CreateRequestWithFile(const base::FilePath upload_file_path, - const std::string& mime_type, - const std::string& filename, - int64_t file_size); - private: - std::unique_ptr CreateResourceRequest( - BlobBuilderCallback blob_builder_callback, - const std::string& content_type, - content::BrowserContext::BlobContextGetter storage_context_getter); - // Uploading blob functions - void UploadDataUI(std::unique_ptr request); + void UploadData(std::unique_ptr request); void OnImportAddComplete(std::unique_ptr response_body); @@ -99,7 +93,6 @@ class IpfsImportWorkerBase { GURL server_endpoint_; std::string key_to_publish_; content::BrowserContext* browser_context_ = nullptr; - scoped_refptr io_task_runner_; base::WeakPtrFactory weak_factory_; }; diff --git a/components/ipfs/import/ipfs_link_import_worker.cc b/components/ipfs/import/ipfs_link_import_worker.cc index 7c42237e1354..421ecdfdeb64 100644 --- a/components/ipfs/import/ipfs_link_import_worker.cc +++ b/components/ipfs/import/ipfs_link_import_worker.cc @@ -82,10 +82,7 @@ void IpfsLinkImportWorker::OnImportDataAvailable(base::FilePath path) { if (filename.empty()) filename = import_url_.host(); - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::MayBlock()}, base::BindOnce(&CalculateFileSize, path), - base::BindOnce(&IpfsLinkImportWorker::CreateRequestWithFile, - weak_factory_.GetWeakPtr(), path, mime_type, filename)); + ImportFile(path, mime_type, filename); } void IpfsLinkImportWorker::RemoveDownloadedFile() { diff --git a/components/ipfs/import/ipfs_text_import_worker.cc b/components/ipfs/import/ipfs_text_import_worker.cc deleted file mode 100644 index cb4eb1751dde..000000000000 --- a/components/ipfs/import/ipfs_text_import_worker.cc +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (c) 2021 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "brave/components/ipfs/import/ipfs_text_import_worker.h" - -#include -#include - -#include "base/command_line.h" -#include "base/files/file_util.h" -#include "base/guid.h" -#include "base/task/post_task.h" -#include "base/task_runner_util.h" -#include "brave/components/ipfs/ipfs_constants.h" -#include "brave/components/ipfs/ipfs_network_utils.h" -#include "content/public/browser/browser_context.h" -#include "net/base/mime_util.h" -#include "storage/browser/blob/blob_data_builder.h" -#include "url/gurl.h" - -namespace { - -const char kIPFSImportTextMimeType[] = "application/octet-stream"; - -std::unique_ptr BuildBlobWithText( - const std::string& text, - std::string mime_type, - std::string filename, - std::string mime_boundary) { - auto blob_builder = - std::make_unique(base::GenerateGUID()); - std::string post_data_header; - net::AddMultipartValueForUploadWithFileName(ipfs::kFileValueName, filename, - text, mime_boundary, mime_type, - &post_data_header); - blob_builder->AppendData(post_data_header); - - std::string post_data_footer = "\r\n"; - net::AddMultipartFinalDelimiterForUpload(mime_boundary, &post_data_footer); - blob_builder->AppendData(post_data_footer); - return blob_builder; -} - -} // namespace - -namespace ipfs { - -IpfsTextImportWorker::IpfsTextImportWorker(content::BrowserContext* context, - const GURL& endpoint, - ImportCompletedCallback callback, - const std::string& text, - const std::string& host) - : IpfsImportWorkerBase(context, endpoint, std::move(callback)) { - StartImportText(text, host); -} - -IpfsTextImportWorker::~IpfsTextImportWorker() = default; - -void IpfsTextImportWorker::StartImportText(const std::string& text, - const std::string& host) { - if (text.empty() || host.empty()) { - return NotifyImportCompleted(IPFS_IMPORT_ERROR_REQUEST_EMPTY); - } - size_t key = base::FastHash(base::as_bytes(base::make_span(text))); - std::string filename = host; - filename += "_"; - filename += std::to_string(key); - std::string mime_boundary = net::GenerateMimeMultipartBoundary(); - auto blob_builder_callback = - base::BindOnce(&BuildBlobWithText, text, kIPFSImportTextMimeType, - filename, mime_boundary); - std::string content_type = kIPFSImportMultipartContentType; - content_type += " boundary="; - content_type += mime_boundary; - StartImport(std::move(blob_builder_callback), content_type, filename); -} - -} // namespace ipfs diff --git a/components/ipfs/import/ipfs_text_import_worker.h b/components/ipfs/import/ipfs_text_import_worker.h deleted file mode 100644 index 7520bdcfb305..000000000000 --- a/components/ipfs/import/ipfs_text_import_worker.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2021 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_TEXT_IMPORT_WORKER_H_ -#define BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_TEXT_IMPORT_WORKER_H_ - -#include - -#include "brave/components/ipfs/import/ipfs_import_worker_base.h" -#include "url/gurl.h" - -namespace ipfs { - -// Implements preparation steps for importing text objects into ipfs. -// Wraps text data to a request object and puts it to the base class -// for the upload using IPFS api -class IpfsTextImportWorker : public IpfsImportWorkerBase { - public: - IpfsTextImportWorker(content::BrowserContext* context, - const GURL& endpoint, - ImportCompletedCallback callback, - const std::string& text, - const std::string& host); - ~IpfsTextImportWorker() override; - - IpfsTextImportWorker(const IpfsTextImportWorker&) = delete; - IpfsTextImportWorker& operator=(const IpfsTextImportWorker&) = delete; - - private: - void StartImportText(const std::string& text, const std::string& host); -}; - -} // namespace ipfs - -#endif // BRAVE_COMPONENTS_IPFS_IMPORT_IPFS_TEXT_IMPORT_WORKER_H_ diff --git a/components/ipfs/ipfs_constants.cc b/components/ipfs/ipfs_constants.cc index 94cd0a3f4c53..42ea47a65854 100644 --- a/components/ipfs/ipfs_constants.cc +++ b/components/ipfs/ipfs_constants.cc @@ -10,6 +10,7 @@ namespace ipfs { const char kAPIKeyGenerateEndpoint[] = "/api/v0/key/gen"; const char kAPIKeyRemoveEndpoint[] = "/api/v0/key/rm"; const char kAPIKeyListEndpoint[] = "/api/v0/key/list"; +const char kAPIKeyImportEndpoint[] = "/api/v0/key/import"; const char kSwarmPeersPath[] = "/api/v0/swarm/peers"; const char kAPIPublishNameEndpoint[] = "/api/v0/name/publish"; const char kConfigPath[] = "/api/v0/config"; @@ -41,5 +42,6 @@ const char kImportDirectory[] = "/brave-imports/"; const char kIPFSImportMultipartContentType[] = "multipart/form-data;"; const char kFileValueName[] = "file"; const char kFileMimeType[] = "application/octet-stream"; - +const char kDirectoryMimeType[] = "application/x-directory"; +const char kIPFSImportTextMimeType[] = "application/octet-stream"; } // namespace ipfs diff --git a/components/ipfs/ipfs_constants.h b/components/ipfs/ipfs_constants.h index 2c66851a7cf5..3eefbf13d767 100644 --- a/components/ipfs/ipfs_constants.h +++ b/components/ipfs/ipfs_constants.h @@ -11,6 +11,7 @@ namespace ipfs { extern const char kAPIKeyListEndpoint[]; extern const char kAPIKeyGenerateEndpoint[]; extern const char kAPIKeyRemoveEndpoint[]; +extern const char kAPIKeyImportEndpoint[]; extern const char kSwarmPeersPath[]; extern const char kConfigPath[]; extern const char kArgQueryParam[]; @@ -38,6 +39,8 @@ extern const char kAPIPublishNameEndpoint[]; extern const char kIPFSImportMultipartContentType[]; extern const char kFileValueName[]; extern const char kFileMimeType[]; +extern const char kDirectoryMimeType[]; +extern const char kIPFSImportTextMimeType[]; // Keep it synced with IPFSResolveMethodTypes in // browser/resources/settings/brave_ipfs_page/brave_ipfs_page.js diff --git a/components/ipfs/ipfs_network_utils.cc b/components/ipfs/ipfs_network_utils.cc index e19c34d687e6..f448d44db357 100644 --- a/components/ipfs/ipfs_network_utils.cc +++ b/components/ipfs/ipfs_network_utils.cc @@ -8,18 +8,37 @@ #include #include #include +#include #include "base/callback.h" #include "base/check.h" +#include "base/files/file_enumerator.h" #include "base/files/file_util.h" #include "base/guid.h" +#include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "brave/components/ipfs/ipfs_constants.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_task_traits.h" #include "net/base/mime_util.h" #include "services/network/public/cpp/simple_url_loader.h" #include "storage/browser/blob/blob_data_builder.h" +#include "storage/browser/blob/blob_impl.h" +#include "storage/browser/blob/blob_storage_context.h" +#include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h" namespace { +struct ImportFileInfo { + ImportFileInfo(base::FilePath full_path, + base::FileEnumerator::FileInfo information) { + path = full_path; + info = information; + } + base::FilePath path; + base::FileEnumerator::FileInfo info; +}; + net::NetworkTrafficAnnotationTag GetIpfsNetworkTrafficAnnotationTag() { return net::DefineNetworkTrafficAnnotation("ipfs_service", R"( semantics { @@ -43,52 +62,65 @@ net::NetworkTrafficAnnotationTag GetIpfsNetworkTrafficAnnotationTag() { )"); } -} // namespace +bool GetRelativePathComponent(const base::FilePath& parent, + const base::FilePath& child, + base::FilePath::StringType* out) { + if (!parent.IsParent(child)) + return false; -namespace ipfs { + std::vector parent_components; + std::vector child_components; + parent.GetComponents(&parent_components); + child.GetComponents(&child_components); -void AddMultipartHeaderForUploadWithFileName(const std::string& value_name, - const std::string& file_name, - const std::string& absolute_path, - const std::string& mime_boundary, - const std::string& content_type, - std::string* post_data) { - DCHECK(post_data); - // First line is the boundary. - post_data->append("--" + mime_boundary + "\r\n"); - if (!absolute_path.empty()) - post_data->append("Abspath: " + absolute_path + "\r\n"); - // Next line is the Content-disposition. - post_data->append("Content-Disposition: form-data; name=\"" + value_name + - "\"; filename=\"" + file_name + "\"\r\n"); - // If Content-type is specified, the next line is that. - post_data->append("Content-Type: " + content_type + "\r\n"); - // Empty string before next content - post_data->append("\r\n"); + size_t i = 0; + while (i < parent_components.size() && + child_components[i] == parent_components[i]) { + ++i; + } + + while (i < child_components.size()) { + out->append(child_components[i]); + if (++i < child_components.size()) + out->append(FILE_PATH_LITERAL("/")); + } + return true; } -int64_t CalculateFileSize(base::FilePath upload_file_path) { - int64_t file_size = -1; - base::GetFileSize(upload_file_path, &file_size); - return file_size; +std::unique_ptr BuildBlobWithText( + const std::string& text, + std::string mime_type, + std::string filename, + std::string mime_boundary) { + auto blob_builder = + std::make_unique(base::GenerateGUID()); + std::string post_data_header; + net::AddMultipartValueForUploadWithFileName(ipfs::kFileValueName, filename, + text, mime_boundary, mime_type, + &post_data_header); + blob_builder->AppendData(post_data_header); + + std::string post_data_footer = "\r\n"; + net::AddMultipartFinalDelimiterForUpload(mime_boundary, &post_data_footer); + blob_builder->AppendData(post_data_footer); + return blob_builder; } std::unique_ptr BuildBlobWithFile( base::FilePath upload_file_path, - size_t file_size, std::string mime_type, std::string filename, - std::string mime_boundary) { + std::string mime_boundary, + size_t file_size) { auto blob_builder = std::make_unique(base::GenerateGUID()); if (filename.empty()) filename = upload_file_path.BaseName().MaybeAsASCII(); std::string post_data_header; - ipfs::AddMultipartHeaderForUploadWithFileName(kFileValueName, filename, + ipfs::AddMultipartHeaderForUploadWithFileName(ipfs::kFileValueName, filename, std::string(), mime_boundary, mime_type, &post_data_header); blob_builder->AppendData(post_data_header); - blob_builder->AppendFile(upload_file_path, /* offset= */ 0, file_size, /* expected_modification_time= */ base::Time()); std::string post_data_footer = "\r\n"; @@ -98,6 +130,40 @@ std::unique_ptr BuildBlobWithFile( return blob_builder; } +std::unique_ptr BuildBlobWithFolder( + base::FilePath upload_path, + std::string mime_boundary, + std::vector files) { + auto blob_builder = + std::make_unique(base::GenerateGUID()); + for (const auto& info : files) { + std::string data_header; + base::FilePath::StringType relative_path; + GetRelativePathComponent(upload_path, info.path, &relative_path); + + std::string mime_type = info.info.IsDirectory() ? ipfs::kDirectoryMimeType + : ipfs::kFileMimeType; + data_header.append("\r\n"); + ipfs::AddMultipartHeaderForUploadWithFileName( + ipfs::kFileValueName, base::FilePath(relative_path).MaybeAsASCII(), + info.path.MaybeAsASCII(), mime_boundary, mime_type, &data_header); + blob_builder->AppendData(data_header); + if (mime_type == ipfs::kFileMimeType) { + blob_builder->AppendFile(info.path, 0, info.info.GetSize(), base::Time()); + } + } + + std::string post_data_footer = "\r\n"; + net::AddMultipartFinalDelimiterForUpload(mime_boundary, &post_data_footer); + blob_builder->AppendData(post_data_footer); + + return blob_builder; +} + +} // namespace + +namespace ipfs { + std::unique_ptr CreateURLLoader( const GURL& gurl, const std::string& method, @@ -116,4 +182,149 @@ std::unique_ptr CreateURLLoader( return url_loader; } +std::unique_ptr CreateResourceRequest( + BlobBuilderCallback blob_builder_callback, + const std::string& content_type, + content::BrowserContext::BlobContextGetter storage_context_getter) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + std::unique_ptr blob_builder = + std::move(blob_builder_callback).Run(); + + auto storage_context = std::move(storage_context_getter).Run(); + std::unique_ptr blob_handle = + storage_context->AddFinishedBlob(std::move(blob_builder)); + + auto blob = blink::mojom::SerializedBlob::New(); + blob->uuid = blob_handle->uuid(); + blob->size = blob_handle->size(); + storage::BlobImpl::Create( + std::make_unique(*blob_handle), + blob->blob.InitWithNewPipeAndPassReceiver()); + // Use a Data Pipe to transfer the blob. + mojo::PendingRemote data_pipe_getter_remote; + mojo::Remote blob_remote(std::move(blob->blob)); + blob_remote->AsDataPipeGetter( + data_pipe_getter_remote.InitWithNewPipeAndPassReceiver()); + + auto request = std::make_unique(); + request->request_body = new network::ResourceRequestBody(); + request->request_body->AppendDataPipe(std::move(data_pipe_getter_remote)); + request->headers.SetHeader(net::HttpRequestHeaders::kContentType, + content_type); + return request; +} + +void AddMultipartHeaderForUploadWithFileName(const std::string& value_name, + const std::string& file_name, + const std::string& absolute_path, + const std::string& mime_boundary, + const std::string& content_type, + std::string* post_data) { + DCHECK(post_data); + // First line is the boundary. + post_data->append("--" + mime_boundary + "\r\n"); + if (!absolute_path.empty()) + post_data->append("Abspath: " + absolute_path + "\r\n"); + // Next line is the Content-disposition. + post_data->append("Content-Disposition: form-data; name=\"" + value_name + + "\"; filename=\"" + file_name + "\"\r\n"); + // If Content-type is specified, the next line is that. + post_data->append("Content-Type: " + content_type + "\r\n"); + // Empty string before next content + post_data->append("\r\n"); +} + +int64_t CalculateFileSize(base::FilePath upload_file_path) { + int64_t file_size = -1; + base::GetFileSize(upload_file_path, &file_size); + return file_size; +} + +void CreateRequestForFile(const base::FilePath& upload_file_path, + content::BrowserContext::BlobContextGetter storage, + const std::string& mime_type, + const std::string& filename, + ResourceRequestGetter request_callback, + size_t file_size) { + std::string mime_boundary = net::GenerateMimeMultipartBoundary(); + auto blob_builder_callback = + base::BindOnce(&BuildBlobWithFile, upload_file_path, mime_type, filename, + mime_boundary, file_size); + std::string content_type = ipfs::kIPFSImportMultipartContentType; + content_type += " boundary="; + content_type += mime_boundary; + + base::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), content::BrowserThread::IO}, + base::BindOnce(&CreateResourceRequest, std::move(blob_builder_callback), + content_type, std::move(storage)), + std::move(request_callback)); +} + +std::vector EnumerateDirectoryFiles(base::FilePath dir_path) { + std::vector files; + base::FileEnumerator file_enum( + dir_path, true, + base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); + for (base::FilePath enum_path = file_enum.Next(); !enum_path.empty(); + enum_path = file_enum.Next()) { + // Skip symlinks. + if (base::IsLink(enum_path)) + continue; + files.push_back(ImportFileInfo(enum_path, file_enum.GetInfo())); + } + + return files; +} + +void CreateRequestForFileList( + ResourceRequestGetter request_callback, + content::BrowserContext::BlobContextGetter storage, + const base::FilePath& folder_path, + std::vector files) { + std::string mime_boundary = net::GenerateMimeMultipartBoundary(); + auto blob_builder_callback = + base::BindOnce(&BuildBlobWithFolder, folder_path.DirName(), mime_boundary, + std::move(files)); + + std::string content_type = ipfs::kIPFSImportMultipartContentType; + content_type += " boundary="; + content_type += mime_boundary; + + base::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), content::BrowserThread::IO}, + base::BindOnce(&CreateResourceRequest, std::move(blob_builder_callback), + content_type, std::move(storage)), + std::move(request_callback)); +} + +void CreateRequestForFolder(const base::FilePath& folder_path, + content::BrowserContext::BlobContextGetter storage, + ResourceRequestGetter request_callback) { + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&EnumerateDirectoryFiles, folder_path), + base::BindOnce(&CreateRequestForFileList, std::move(request_callback), + std::move(storage), folder_path)); +} + +void CreateRequestForText(const std::string& text, + const std::string& filename, + content::BrowserContext::BlobContextGetter storage, + ResourceRequestGetter request_callback) { + std::string mime_boundary = net::GenerateMimeMultipartBoundary(); + auto blob_builder_callback = + base::BindOnce(&BuildBlobWithText, text, ipfs::kIPFSImportTextMimeType, + filename, mime_boundary); + std::string content_type = kIPFSImportMultipartContentType; + content_type += " boundary="; + content_type += mime_boundary; + + base::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), content::BrowserThread::IO}, + base::BindOnce(&CreateResourceRequest, std::move(blob_builder_callback), + content_type, std::move(storage)), + std::move(request_callback)); +} + } // namespace ipfs diff --git a/components/ipfs/ipfs_network_utils.h b/components/ipfs/ipfs_network_utils.h index e37bb3f7fd1a..8afbe1b72888 100644 --- a/components/ipfs/ipfs_network_utils.h +++ b/components/ipfs/ipfs_network_utils.h @@ -10,6 +10,8 @@ #include #include "base/callback.h" +#include "base/files/file_enumerator.h" +#include "content/public/browser/browser_context.h" #include "services/network/public/cpp/simple_url_loader.h" #include "url/gurl.h" @@ -39,13 +41,6 @@ void AddMultipartHeaderForUploadWithFileName(const std::string& value_name, const std::string& content_type, std::string* post_data); -std::unique_ptr BuildBlobWithFile( - base::FilePath upload_file_path, - size_t file_size, - std::string mime_type, - std::string filename, - std::string mime_boundary); - int64_t CalculateFileSize(base::FilePath upload_file_path); using BlobBuilderCallback = @@ -56,6 +51,24 @@ std::unique_ptr CreateURLLoader( const std::string& method, std::unique_ptr request = nullptr); +using ResourceRequestGetter = + base::OnceCallback)>; + +void CreateRequestForFile(const base::FilePath& upload_file_path, + content::BrowserContext::BlobContextGetter storage, + const std::string& mime_type, + const std::string& filename, + ResourceRequestGetter request_callback, + size_t file_size); + +void CreateRequestForFolder(const base::FilePath& folder_path, + content::BrowserContext::BlobContextGetter storage, + ResourceRequestGetter request_callback); + +void CreateRequestForText(const std::string& text, + const std::string& filename, + content::BrowserContext::BlobContextGetter storage, + ResourceRequestGetter request_callback); } // namespace ipfs #endif // BRAVE_COMPONENTS_IPFS_IPFS_NETWORK_UTILS_H_ diff --git a/components/ipfs/ipfs_network_utils_unittest.cc b/components/ipfs/ipfs_network_utils_unittest.cc index 911098248cbb..23db54c4edd8 100644 --- a/components/ipfs/ipfs_network_utils_unittest.cc +++ b/components/ipfs/ipfs_network_utils_unittest.cc @@ -7,9 +7,13 @@ #include #include +#include #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_browser_context.h" +#include "services/network/public/cpp/data_element.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_item.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,7 +25,32 @@ class IpfsNetwrokUtilsUnitTest : public testing::Test { IpfsNetwrokUtilsUnitTest() {} ~IpfsNetwrokUtilsUnitTest() override = default; + void SetUp() override { + browser_context_ = std::make_unique(); + } + + base::FilePath CreateCustomTestFile(const base::FilePath& dir, + const std::string& filename, + const std::string& content) { + base::FilePath file_path = dir.AppendASCII(filename); + + base::WriteFile(file_path, content); + return file_path; + } + content::BrowserContext* browser_context() { return browser_context_.get(); } + void ValidateRequest(base::OnceClosure callback, + std::unique_ptr request) { + ASSERT_TRUE(request.get()); + ASSERT_EQ(request->request_body->elements()->size(), size_t(1)); + ASSERT_EQ(request->request_body->elements()->front().type(), + network::mojom::DataElementDataView::Tag::kDataPipe); + if (callback) + std::move(callback).Run(); + } + private: + content::BrowserTaskEnvironment task_environment_; + std::unique_ptr browser_context_; }; TEST_F(IpfsNetwrokUtilsUnitTest, AddMultipartHeaderForUploadWithFileName) { @@ -40,24 +69,6 @@ TEST_F(IpfsNetwrokUtilsUnitTest, AddMultipartHeaderForUploadWithFileName) { EXPECT_STREQ(ref_output, post_data.c_str()); } -TEST_F(IpfsNetwrokUtilsUnitTest, BuildFileBlob) { - base::FilePath upload_file_path(FILE_PATH_LITERAL("test_file")); - size_t file_size = 100; - std::string mime_type = "test/type"; - std::string filename = "test_name"; - std::string mime_boundary = "mime_boundary"; - std::unique_ptr builder = BuildBlobWithFile( - upload_file_path, file_size, mime_type, filename, mime_boundary); - - EXPECT_EQ(builder->items().size(), (size_t)3); - EXPECT_EQ(builder->items()[0]->item()->type(), - storage::BlobDataItem::Type::kBytes); - EXPECT_EQ(builder->items()[1]->item()->type(), - storage::BlobDataItem::Type::kFile); - EXPECT_EQ(builder->items()[2]->item()->type(), - storage::BlobDataItem::Type::kBytes); -} - TEST_F(IpfsNetwrokUtilsUnitTest, FileSizeCalculation) { base::ScopedTempDir dir; ASSERT_TRUE(dir.CreateUniqueTempDir()); @@ -73,4 +84,58 @@ TEST_F(IpfsNetwrokUtilsUnitTest, FileSizeCalculation) { EXPECT_EQ(CalculateFileSize(nonexistent_file_path), -1); } +TEST_F(IpfsNetwrokUtilsUnitTest, CreateRequestForFileTest) { + base::ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + std::string content = "test\n\rmultiline\n\rcontent"; + std::string filename = "test_name"; + base::FilePath upload_file_path = + CreateCustomTestFile(dir.GetPath(), filename, content); + size_t file_size = content.size(); + std::string mime_type = "test/type"; + std::string mime_boundary = "mime_boundary"; + auto storage = + content::BrowserContext::GetBlobStorageContext(browser_context()); + base::RunLoop run_loop; + auto upload_callback = + base::BindOnce(&IpfsNetwrokUtilsUnitTest::ValidateRequest, + base::Unretained(this), run_loop.QuitClosure()); + CreateRequestForFile(upload_file_path, storage, mime_type, filename, + std::move(upload_callback), file_size); + run_loop.Run(); +} + +TEST_F(IpfsNetwrokUtilsUnitTest, CreateRequestForTextTest) { + std::string text = "test\n\rmultiline\n\rcontent"; + std::string filename = "test_name"; + std::string mime_type = "test/type"; + std::string mime_boundary = "mime_boundary"; + auto storage = + content::BrowserContext::GetBlobStorageContext(browser_context()); + base::RunLoop run_loop; + auto upload_callback = + base::BindOnce(&IpfsNetwrokUtilsUnitTest::ValidateRequest, + base::Unretained(this), run_loop.QuitClosure()); + CreateRequestForText(text, filename, storage, std::move(upload_callback)); + run_loop.Run(); +} + +TEST_F(IpfsNetwrokUtilsUnitTest, CreateRequestForFolderTest) { + base::ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + std::string content = "test\n\rmultiline\n\rcontent"; + std::string filename = "test_name"; + CreateCustomTestFile(dir.GetPath(), filename, content); + std::string mime_type = "test/type"; + std::string mime_boundary = "mime_boundary"; + auto storage = + content::BrowserContext::GetBlobStorageContext(browser_context()); + base::RunLoop run_loop; + auto upload_callback = + base::BindOnce(&IpfsNetwrokUtilsUnitTest::ValidateRequest, + base::Unretained(this), run_loop.QuitClosure()); + CreateRequestForFolder(dir.GetPath(), storage, std::move(upload_callback)); + run_loop.Run(); +} + } // namespace ipfs diff --git a/components/ipfs/ipfs_service.cc b/components/ipfs/ipfs_service.cc index e4a0d31a076b..cd11ac306bea 100644 --- a/components/ipfs/ipfs_service.cc +++ b/components/ipfs/ipfs_service.cc @@ -16,11 +16,8 @@ #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/task_runner_util.h" -#include "brave/components/ipfs/import/ipfs_directory_import_worker.h" -#include "brave/components/ipfs/import/ipfs_file_import_worker.h" #include "brave/components/ipfs/import/ipfs_import_worker_base.h" #include "brave/components/ipfs/import/ipfs_link_import_worker.h" -#include "brave/components/ipfs/import/ipfs_text_import_worker.h" #include "brave/components/ipfs/ipfs_constants.h" #include "brave/components/ipfs/ipfs_json_parser.h" #include "brave/components/ipfs/ipfs_ports.h" @@ -292,9 +289,9 @@ void IpfsService::ImportFileToIpfs(const base::FilePath& path, auto import_completed_callback = base::BindOnce(&IpfsService::OnImportFinished, weak_factory_.GetWeakPtr(), std::move(callback), hash); - importers_[hash] = std::make_unique( - context_, server_endpoint_, std::move(import_completed_callback), path, - key); + importers_[hash] = std::make_unique( + context_, server_endpoint_, std::move(import_completed_callback), key); + importers_[hash]->ImportFile(path); } void IpfsService::ImportLinkToIpfs(const GURL& url, @@ -345,9 +342,9 @@ void IpfsService::ImportDirectoryToIpfs(const base::FilePath& folder, auto import_completed_callback = base::BindOnce(&IpfsService::OnImportFinished, weak_factory_.GetWeakPtr(), std::move(callback), hash); - importers_[hash] = std::make_unique( - context_, server_endpoint_, std::move(import_completed_callback), folder, - key); + importers_[hash] = std::make_unique( + context_, server_endpoint_, std::move(import_completed_callback), key); + importers_[hash]->ImportFolder(folder); } void IpfsService::ImportTextToIpfs(const std::string& text, @@ -371,9 +368,10 @@ void IpfsService::ImportTextToIpfs(const std::string& text, auto import_completed_callback = base::BindOnce(&IpfsService::OnImportFinished, weak_factory_.GetWeakPtr(), std::move(callback), hash); - importers_[hash] = std::make_unique( - context_, server_endpoint_, std::move(import_completed_callback), text, - host); + importers_[hash] = std::make_unique( + context_, server_endpoint_, std::move(import_completed_callback)); + + importers_[hash]->ImportText(text, host); } void IpfsService::OnImportFinished(ipfs::ImportCompletedCallback callback,