* Copyright (C) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef REQUEST_PRE_DOWNLOAD_H
#define REQUEST_PRE_DOWNLOAD_H
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <vector>
namespace rust {
inline namespace cxxbridge1 {
template<typename T> class Box;
template<typename T> class Slice;
}
}
namespace OHOS::Request {
struct RustData;
struct TaskHandle;
struct CacheDownloadService;
struct CacheDownloadError;
struct RustDownloadInfo;
* @brief Running state of a preload task.
*/
enum class PreloadState {
INIT,
RUNNING,
SUCCESS,
FAIL,
CANCEL,
};
* @brief SSL/TLS protocol type used by a preload request.
*/
enum SslType {
DEFAULT,
TLS,
TLCP,
};
* @brief Cache write strategy.
*/
enum class CacheStrategy : uint32_t {
FORCE = 0,
LAZY = 1,
};
* Task retry configuration.
*/
struct RetryOptions {
* Maximum number of retry attempts.
* The default value is 1.
* The minimum value is 0.
* The maximum value is 10.
* When set to 0, no retries will be performed.
*/
int32_t maxRetryCount;
};
* Task timeout configuration.
*/
struct TimeoutOptions {
* Network availability check timeout, in seconds.
* The default value is 20.
* The minimum value is 0.
* The maximum value is 20.
* When set to 0, no check will be performed.
*/
int32_t networkCheckTimeout;
* Complete HTTP request-response cycle timeout, in seconds.
* The default value is 60.
* The minimum value is 1.
*/
int32_t httpTotalTimeout;
};
* @brief Safe slice wrapper template across the Rust/C++ boundary, accessing
* contiguous memory by element count.
*/
template<typename T> class Slice {
public:
Slice(std::unique_ptr<rust::Slice<T>> &&slice);
~Slice();
T *data() const noexcept;
std::size_t size() const noexcept;
std::size_t length() const noexcept;
bool empty() const noexcept;
T &operator[](std::size_t n) const noexcept;
private:
std::unique_ptr<rust::Slice<T>> slice_;
};
* @brief Holder of preload downloaded data, bridging Rust-side RustData.
*
* Move-only. It provides two access styles: a C++ byte slice and a raw Rust
* slice, used to safely pass downloaded binary content across language
* boundaries.
*/
class Data {
public:
Data(rust::Box<RustData> &&data);
Data(Data &&) noexcept;
~Data();
Data &operator=(Data &&) &noexcept;
Slice<const uint8_t> bytes() const;
rust::Slice<const uint8_t> rustSlice() const;
private:
RustData *data_;
};
* @brief Category of preload errors.
*/
enum ErrorKind {
HTTP,
IO,
DNS,
TCP,
SSL,
OTHERS
};
* @brief Statistics of a single download (move-only), bridging Rust-side
* RustDownloadInfo.
*
* Provides metrics such as the duration of each download phase and the target
* address, used for performance analysis and issue triage.
*/
class CppDownloadInfo {
public:
CppDownloadInfo(rust::Box<RustDownloadInfo> rust_info);
CppDownloadInfo(CppDownloadInfo &&other) noexcept;
CppDownloadInfo &operator=(CppDownloadInfo &&other) noexcept;
CppDownloadInfo(const CppDownloadInfo &) = delete;
CppDownloadInfo &operator=(const CppDownloadInfo &) = delete;
~CppDownloadInfo();
double dns_time() const;
double connect_time() const;
double tls_time() const;
double first_send_time() const;
double first_recv_time() const;
double redirect_time() const;
double total_time() const;
int64_t resource_size() const;
std::string server_addr() const;
std::vector<std::string> dns_servers() const;
private:
RustDownloadInfo *rust_info_;
};
* @brief Preload failure information (move-only), aggregating the error code,
* description, category and download statistics.
*/
class PreloadError {
public:
PreloadError(rust::Box<CacheDownloadError> &&error, rust::Box<RustDownloadInfo> &&rust_info);
PreloadError(PreloadError &&) noexcept;
PreloadError &operator=(PreloadError &&) &noexcept;
~PreloadError();
int32_t GetCode() const;
std::string GetMessage() const;
ErrorKind GetErrorKind() const;
std::shared_ptr<CppDownloadInfo> GetDownloadInfo() const;
private:
CacheDownloadError *error_;
std::shared_ptr<CppDownloadInfo> download_info_;
};
* @brief Set of event callbacks for a preload task, implemented by the caller
* and passed to load().
*/
struct PreloadCallback {
std::function<void(const std::shared_ptr<Data> &&, const std::string &TaskId)> OnSuccess;
std::function<void(const PreloadError &, const std::string &TaskId)> OnFail;
std::function<void()> OnCancel;
std::function<void(uint64_t current, uint64_t total)> OnProgress;
};
* @brief Preload task handle (move-only), used to query state or actively
* cancel after the task completes.
*/
class PreloadHandle {
public:
PreloadHandle(PreloadHandle &&) noexcept;
PreloadHandle(rust::Box<TaskHandle>);
PreloadHandle &operator=(PreloadHandle &&) &noexcept;
~PreloadHandle();
void Cancel();
std::string GetTaskId();
bool IsFinish();
PreloadState GetState();
private:
TaskHandle *handle_;
};
* @brief Optional configuration for a single preload request.
*/
struct PreloadOptions {
std::vector<std::tuple<std::string, std::string>> headers;
SslType sslType;
std::string caPath;
RetryOptions retry;
TimeoutOptions timeout;
};
* @brief External entry of preload (cache download), as a singleton.
*
* Provides capabilities such as starting a preload by URL, cancelling,
* removing and querying by URL, cache capacity and path configuration,
* global retry/timeout configuration, and synchronously fetching cached
* data.
*/
class Preload {
public:
Preload();
* @brief Get the Preload singleton pointer.
* @return Singleton pointer, unique within the process.
*/
static Preload *GetInstance();
virtual ~Preload() = default;
void Cancel(std::string const &url);
void Remove(std::string const &url);
bool Contains(std::string const &url);
void SetRamCacheSize(uint64_t size);
void SetFileCacheSize(uint64_t size);
void SetDownloadInfoListSize(uint16_t size);
static void SetFileCachePath(const std::string &path);
void ClearMemoryCache();
void ClearFileCache();
void SetGlobalRetryOptions(const RetryOptions &options);
void SetGlobalTimeoutOptions(const TimeoutOptions &options);
* @brief Start a preload for the specified URL.
* @param url Resource address to be preloaded.
* @param callback Task event callback, must not be null.
* @param options Optional configuration for this request; when null, global config is used.
* @param update Whether to force-refresh cached content (true means re-download even if cached).
* @return Task handle, which can be used to cancel or query state later.
*/
std::shared_ptr<PreloadHandle> load(std::string const &url, std::unique_ptr<PreloadCallback>,
std::unique_ptr<PreloadOptions> options = nullptr, bool update = false);
* @brief Synchronously fetch the cached data for the specified URL.
* @param url Resource address.
* @return Returns the data if the cache is hit, otherwise an empty optional.
*/
std::optional<Data> fetch(std::string const &url);
* @brief Get the download statistics for the specified URL.
* @param url Resource address.
* @return Returns the statistics if a record exists, otherwise an empty optional.
*/
std::optional<CppDownloadInfo> GetDownloadInfo(std::string const &url);
private:
const CacheDownloadService *agent_;
};
}
#endif