3535#include " olp/core/thread/Atomic.h"
3636#include " olp/core/utils/Url.h"
3737
38+ #ifdef OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
39+ #include " context/ContextInternal.h"
40+ #include " olp/core/context/EnterBackgroundSubscriber.h"
41+ #endif // OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
42+
3843namespace {
3944constexpr auto kLogTag = " OlpClient" ;
4045constexpr auto kApiKeyParam = " apiKey=" ;
@@ -52,6 +57,75 @@ struct RequestSettings {
5257 std::chrono::milliseconds current_backdown_period{0 };
5358 const std::chrono::milliseconds max_wait_time{0 };
5459};
60+
61+ #ifdef OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
62+ class EnterBackgroundSubscriberImpl
63+ : public olp::context::EnterBackgroundSubscriber {
64+ public:
65+ struct Timeouts {
66+ std::chrono::seconds foreground_timeout{0 };
67+ std::chrono::seconds background_timeout{0 };
68+ };
69+
70+ void OnEnterBackground () override {
71+ std::lock_guard<std::mutex> lock (mutex_);
72+ in_background_ = true ;
73+ std::for_each (states_.begin (), states_.end (),
74+ [&](bool value) { value = true ; });
75+ }
76+
77+ void OnExitBackground () override {
78+ std::lock_guard<std::mutex> lock (mutex_);
79+ in_background_ = false ;
80+ }
81+
82+ bool Wait (olp::client::Condition& client_condition, Timeouts timeouts) {
83+ std::list<bool >::iterator state_itr;
84+
85+ auto init_state = [&]() -> bool {
86+ std::lock_guard<std::mutex> lock (mutex_);
87+ state_itr = states_.insert (states_.end (), in_background_);
88+ return in_background_;
89+ };
90+
91+ auto pop_state = [&]() -> bool {
92+ std::lock_guard<std::mutex> lock (mutex_);
93+ bool state = *state_itr;
94+ states_.erase (state_itr);
95+ return state;
96+ };
97+
98+ const bool started_in_background = init_state ();
99+ const auto condition_triggered = client_condition.Wait (
100+ started_in_background ? timeouts.background_timeout
101+ : timeouts.foreground_timeout );
102+
103+ const bool stored_state = pop_state ();
104+ if ((condition_triggered &&
105+ (started_in_background || started_in_background == stored_state)) ||
106+ timeouts.background_timeout <= timeouts.foreground_timeout ) {
107+ return condition_triggered;
108+ }
109+
110+ return client_condition.Wait (timeouts.background_timeout -
111+ timeouts.foreground_timeout );
112+ }
113+
114+ private:
115+ std::mutex mutex_;
116+ bool in_background_ = false ;
117+ std::list<bool > states_;
118+ };
119+
120+ static std::shared_ptr<EnterBackgroundSubscriberImpl> gBackgroundSubscriber =
121+ []() {
122+ auto impl = std::make_shared<EnterBackgroundSubscriberImpl>();
123+ olp::context::ContextInternal::SubscribeEnterBackground (impl);
124+ return impl;
125+ }();
126+
127+ #endif // OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
128+
55129} // namespace
56130
57131namespace olp {
@@ -285,6 +359,10 @@ HttpResponse SendRequest(const http::NetworkRequest& request,
285359
286360 http::SendOutcome outcome{http::ErrorCode::CANCELLED_ERROR};
287361 const auto timeout = std::chrono::seconds (retry_settings.timeout );
362+ #ifdef OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
363+ const auto background_timeout =
364+ std::chrono::seconds (retry_settings.background_timeout );
365+ #endif // OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
288366
289367 context.ExecuteOrCancelled (
290368 [&]() {
@@ -321,7 +399,14 @@ HttpResponse SendRequest(const http::NetworkRequest& request,
321399 return ToHttpResponse (outcome);
322400 }
323401
402+ #ifdef OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
403+ auto backgroundSubscriber = gBackgroundSubscriber ;
404+ const auto condition_triggered = backgroundSubscriber->Wait (
405+ response_data->condition , {timeout, background_timeout});
406+ #else
324407 const auto condition_triggered = response_data->condition .Wait (timeout);
408+ #endif // OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
409+
325410 if (!condition_triggered) {
326411 OLP_SDK_LOG_WARNING_F (
327412 kLogTag ,
@@ -605,6 +690,10 @@ CancellationToken OlpClient::OlpClientImpl::CallApi(
605690 network_request->WithSettings (
606691 http::NetworkSettings ()
607692 .WithConnectionTimeout (retry_settings.connection_timeout )
693+ #ifdef OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
694+ .WithBackgroundConnectionTimeout (
695+ retry_settings.background_connection_timeout )
696+ #endif // OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
608697 .WithTransferTimeout (retry_settings.transfer_timeout )
609698 .WithProxySettings (std::move (proxy)));
610699
@@ -642,6 +731,10 @@ HttpResponse OlpClient::OlpClientImpl::CallApi(
642731 http::NetworkSettings ()
643732 .WithTransferTimeout (retry_settings.transfer_timeout )
644733 .WithConnectionTimeout (retry_settings.connection_timeout )
734+ #ifdef OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
735+ .WithBackgroundConnectionTimeout (
736+ retry_settings.background_connection_timeout )
737+ #endif // OLP_SDK_NETWORK_IOS_BACKGROUND_DOWNLOAD
645738 .WithProxySettings (
646739 settings_.proxy_settings .value_or (http::NetworkProxySettings ()));
647740
0 commit comments