diff options
| author | Rider Linden <rider@lindenlab.com> | 2026-10-02 09:29:55 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-10-02 09:29:55 -0700 |
| commit | 48e1f6f25b952eeb35e891cd73265e652198cae6 (patch) | |
| tree | 334d05075af85eebca7477078e6ec95e78a510c3 /indra | |
| parent | 8c98605cae0ed5e4d0d70e806703ef13f277e245 (diff) | |
| parent | 01786bf78c825cce2639c482bfc97ae5f3161a1b (diff) | |
Merge branch 'release/26.4' into rider/issue-710
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llfilesystem/lldiriterator.cpp | 2 | ||||
| -rw-r--r-- | indra/llfilesystem/lldiskcache.cpp | 16 | ||||
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
| -rw-r--r-- | indra/newview/llbuycurrencyhtml.cpp | 101 | ||||
| -rw-r--r-- | indra/newview/llbuycurrencyhtml.h | 19 | ||||
| -rw-r--r-- | indra/newview/llfloaterbuycurrency.cpp | 40 | ||||
| -rw-r--r-- | indra/newview/llfloaterbuycurrency.h | 16 |
7 files changed, 175 insertions, 30 deletions
diff --git a/indra/llfilesystem/lldiriterator.cpp b/indra/llfilesystem/lldiriterator.cpp index ca00d25fb7..ec6d1726f0 100644 --- a/indra/llfilesystem/lldiriterator.cpp +++ b/indra/llfilesystem/lldiriterator.cpp @@ -69,7 +69,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) if (!is_dir) { - LL_WARNS() << "Invalid path: \"" << dir_path.string() << "\"" << LL_ENDL; + LL_WARNS() << "Invalid path: \"" << dirname << "\"" << LL_ENDL; return; } diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp index e7b43e15e2..5af801a1df 100644 --- a/indra/llfilesystem/lldiskcache.cpp +++ b/indra/llfilesystem/lldiskcache.cpp @@ -34,6 +34,7 @@ #include "llapp.h" #include "llassettype.h" #include "lldir.h" +#include "llstring.h" #include <chrono> #include <filesystem> @@ -116,14 +117,14 @@ void LLDiskCache::purge() } if (std::filesystem::is_regular_file(*iter, ec) && !ec) { - if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos) + if (fsyspath((*iter).path()).string().find(CACHE_FILENAME_PREFIX) != std::string::npos) { uintmax_t file_size = std::filesystem::file_size(*iter, ec); if (ec) { continue; } - const std::string file_path = (*iter).path().string(); + const std::string file_path = fsyspath((*iter).path()).string(); const std::filesystem::file_time_type file_time = std::filesystem::last_write_time(*iter, ec); if (ec) { @@ -165,7 +166,7 @@ void LLDiskCache::purge() } if (should_remove) { - std::filesystem::remove(entry.second.second, ec); + std::filesystem::remove(fsyspath(entry.second.second), ec); if (ec) { LL_WARNS() << "Failed to delete cache file " << entry.second.second << ": " << ec.message() << LL_ENDL; @@ -245,7 +246,7 @@ void LLDiskCache::clearCache() { if (std::filesystem::is_regular_file(*iter, ec) && !ec) { - if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos) + if (fsyspath((*iter).path()).string().find(CACHE_FILENAME_PREFIX) != std::string::npos) { std::filesystem::remove(*iter, ec); if (ec) @@ -274,8 +275,9 @@ void LLDiskCache::removeOldVFSFiles() { if (std::filesystem::is_regular_file(*iter, ec) && !ec) { - if (((*iter).path().string().find(CACHE_FORMAT) != std::string::npos) || - ((*iter).path().string().find(DB_FORMAT) != std::string::npos)) + const std::string file_path = fsyspath((*iter).path()).string(); + if ((file_path.find(CACHE_FORMAT) != std::string::npos) || + (file_path.find(DB_FORMAT) != std::string::npos)) { std::filesystem::remove(*iter, ec); if (ec) @@ -311,7 +313,7 @@ uintmax_t LLDiskCache::dirFileSize(const std::string& dir) { if (std::filesystem::is_regular_file(*iter, ec) && !ec) { - if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos) + if (fsyspath((*iter).path()).string().find(CACHE_FILENAME_PREFIX) != std::string::npos) { uintmax_t file_size = std::filesystem::file_size(*iter, ec); if (!ec) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ba44b68307..f6f11f9578 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1194,6 +1194,17 @@ <key>Value</key> <string>https://accounts.secondlife.com/packs/floater?lang=[LANGUAGE]&shortfall=[SHORTFALL]</string> </map> + <key>BuyCurrencyAddPaymentURL</key> + <map> + <key>Comment</key> + <string>URL the viewer probes at login; a 200 means the L$ packs floater handles residents without a payment method</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>https://accounts.secondlife.com/packs/floater/add-payment-enabled</string> + </map> <key>PaymentMethodURL</key> <map> <key>Comment</key> diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp index 9ad068cf7f..f5bc3b5357 100644 --- a/indra/newview/llbuycurrencyhtml.cpp +++ b/indra/newview/llbuycurrencyhtml.cpp @@ -89,6 +89,8 @@ public: LLBuyCurrencyHTMLHandler gBuyCurrencyHTMLHandler; bool LLBuyCurrencyHTML::sWebFloaterEnabled = false; +bool LLBuyCurrencyHTML::sAddPaymentEnabled = false; +LLFetchAvatarPaymentInfo* LLBuyCurrencyHTML::sPaymentInfoRequest = NULL; //////////////////////////////////////////////////////////////////////////////// // static @@ -110,11 +112,37 @@ static void checkFeatureFlag_coro(std::string check_url) } // static +static void checkAddPaymentFlag_coro(std::string check_url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter = std::make_shared<LLCoreHttpUtil::HttpCoroutineAdapter>("CheckBuyCurrencyAddPaymentURL", httpPolicy); + LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>(); + + // a redirect to some other page that answers 200 must not read as enabled + LLCore::HttpOptions::ptr_t httpOptions = std::make_shared<LLCore::HttpOptions>(); + httpOptions->setRetries(0); + httpOptions->setFollowRedirects(false); + + LLSD result = httpAdapter->getRawAndSuspend(httpRequest, check_url, httpOptions); + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LLBuyCurrencyHTML::sAddPaymentEnabled = status.isHttpStatus() && status.getType() == 200; + LL_INFOS("LLBuyCurrency") << "Add payment probe returned " << status.toString() + << ", in-floater add payment " << (LLBuyCurrencyHTML::sAddPaymentEnabled ? "enabled" : "disabled") << LL_ENDL; +} + +// static void LLBuyCurrencyHTML::checkFeatureFlag() { std::string check_url = LLFloaterBuyCurrencyHTML::buildURL(); LLCoros::instance().launch("checkFeatureFlag_coro", [check_url]() { checkFeatureFlag_coro(check_url); }); + + std::string add_payment_url = gSavedSettings.getString("BuyCurrencyAddPaymentURL"); + LLCoros::instance().launch("checkAddPaymentFlag_coro", + [add_payment_url]() { checkAddPaymentFlag_coro(add_payment_url); }); } //////////////////////////////////////////////////////////////////////////////// @@ -124,15 +152,7 @@ void LLBuyCurrencyHTML::checkFeatureFlag() // the case where the amount is not requested. void LLBuyCurrencyHTML::openCurrencyFloater() { - if (gSavedSettings.getBOOL("BuyCurrencyHTML") && sWebFloaterEnabled) - { - LLBuyCurrencyHTML::showDialog(); - } - else - { - // legacy version - LLFloaterBuyCurrency::buyCurrency(); - } + routeCurrencyRequest(false, LLStringUtil::null, 0); } //////////////////////////////////////////////////////////////////////////////// @@ -142,19 +162,68 @@ void LLBuyCurrencyHTML::openCurrencyFloater() // the case where the amount and a string to display are requested. void LLBuyCurrencyHTML::openCurrencyFloater( const std::string& message, S32 sum ) { - if (gSavedSettings.getBOOL("BuyCurrencyHTML") && sWebFloaterEnabled) + routeCurrencyRequest(true, message, sum); +} + +//////////////////////////////////////////////////////////////////////////////// +// static +// Without the in-floater add payment flow, the web floater is opened only for +// residents with payment info on file; the rest go to the LindeX payment page. +void LLBuyCurrencyHTML::routeCurrencyRequest( bool has_target, const std::string& message, S32 sum ) +{ + if (!gSavedSettings.getBOOL("BuyCurrencyHTML") || !sWebFloaterEnabled) { - LLBuyCurrencyHTML::showDialog(sum - gStatusBar->getBalance()); - LLFloaterBuyCurrencyHTML* floater = dynamic_cast<LLFloaterBuyCurrencyHTML*>(LLFloaterReg::getInstance("buy_currency_html")); - if (floater) + // legacy version, which runs its own payment info check + if (has_target) { - floater->setFallbackContext(message, sum); + LLFloaterBuyCurrency::buyCurrency(message, sum); } + else + { + LLFloaterBuyCurrency::buyCurrency(); + } + } + else if (sAddPaymentEnabled) + { + openWebFloater(has_target, message, sum); } else { - // legacy version - LLFloaterBuyCurrency::buyCurrency( message, sum ); + delete sPaymentInfoRequest; + sPaymentInfoRequest = new LLFetchAvatarPaymentInfo( + [has_target, message, sum](bool has_piof) + { + delete sPaymentInfoRequest; + sPaymentInfoRequest = NULL; + + if (has_piof) + { + openWebFloater(has_target, message, sum); + } + else + { + LL_INFOS("LLBuyCurrency") << "No payment info on file, opening payment method page" << LL_ENDL; + LLFloaterBuyCurrency::openPaymentMethodPage(); + } + }); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLBuyCurrencyHTML::openWebFloater( bool has_target, const std::string& message, S32 sum ) +{ + if (!has_target) + { + LLBuyCurrencyHTML::showDialog(); + return; + } + + LLBuyCurrencyHTML::showDialog(sum - gStatusBar->getBalance()); + LLFloaterBuyCurrencyHTML* floater = dynamic_cast<LLFloaterBuyCurrencyHTML*>(LLFloaterReg::getInstance("buy_currency_html")); + if (floater) + { + floater->setFallbackContext(message, sum); } } diff --git a/indra/newview/llbuycurrencyhtml.h b/indra/newview/llbuycurrencyhtml.h index 2f78199dcb..c8a98c42a9 100644 --- a/indra/newview/llbuycurrencyhtml.h +++ b/indra/newview/llbuycurrencyhtml.h @@ -29,6 +29,8 @@ #include "llsingleton.h" +class LLFetchAvatarPaymentInfo; + class LLBuyCurrencyHTML { public: @@ -45,10 +47,25 @@ class LLBuyCurrencyHTML // close (and destroy) the currency floater static void closeDialog(); - // probe BuyCurrencyPacksURL once at login; clears sWebFloaterEnabled if 501 + // probe BuyCurrencyPacksURL once at login; clears sWebFloaterEnabled if 501. + // also launches the BuyCurrencyAddPaymentURL probe that sets sAddPaymentEnabled static void checkFeatureFlag(); static bool sWebFloaterEnabled; + + // true only when BuyCurrencyAddPaymentURL answered 200, meaning the web floater + // can add a payment method; otherwise residents without one are sent to the LindeX + static bool sAddPaymentEnabled; + + private: + // route to the legacy floater, the web floater, or the LindeX payment page + static void routeCurrencyRequest( bool has_target, const std::string& message, S32 sum ); + + // open the web floater, with the shortfall and fallback context when there is a target + static void openWebFloater( bool has_target, const std::string& message, S32 sum ); + + // pending payment info check made before opening the web floater + static LLFetchAvatarPaymentInfo* sPaymentInfoRequest; }; #endif // LL_LLBUYCURRENCYHTML_H diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index 56b3229fda..7533145625 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -338,19 +338,39 @@ void LLFloaterBuyCurrency::handleBuyCurrency(bool has_piof, bool has_target, con } else { - const std::string& grid_id = LLGridManager::getInstance()->getGridId(); - const std::string& grid_id_lower = utf8str_tolower(grid_id); - const std::string url = gSavedSettings.getString(grid_id_lower == "damballah" ? "PaymentMethodStagingURL" : "PaymentMethodURL"); - LLWeb::loadURL(url); + openPaymentMethodPage(); } } +// static +void LLFloaterBuyCurrency::openPaymentMethodPage() +{ + const std::string& grid_id = LLGridManager::getInstance()->getGridId(); + const std::string& grid_id_lower = utf8str_tolower(grid_id); + const std::string url = gSavedSettings.getString(grid_id_lower == "damballah" ? "PaymentMethodStagingURL" : "PaymentMethodURL"); + LLWeb::loadURL(url); +} + LLFetchAvatarPaymentInfo::LLFetchAvatarPaymentInfo(bool has_target, const std::string& name, S32 price) : mAvatarID(gAgent.getID()), mHasTarget(has_target), mPrice(price), mName(name) { + sendRequest(); +} + +LLFetchAvatarPaymentInfo::LLFetchAvatarPaymentInfo(const callback_t& cb) +: mAvatarID(gAgent.getID()), + mHasTarget(false), + mPrice(0), + mCallback(cb) +{ + sendRequest(); +} + +void LLFetchAvatarPaymentInfo::sendRequest() +{ LLAvatarPropertiesProcessor* processor = LLAvatarPropertiesProcessor::getInstance(); // register ourselves as an observer processor->addObserver(mAvatarID, this); @@ -369,6 +389,16 @@ void LLFetchAvatarPaymentInfo::processProperties(void* data, EAvatarProcessorTyp if (data && type == APT_PROPERTIES) { LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); - LLFloaterBuyCurrency::handleBuyCurrency(LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(avatar_data), mHasTarget, mName, mPrice); + bool has_piof = LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(avatar_data); + if (mCallback) + { + // call a local copy, since the callback may delete this observer + callback_t cb = mCallback; + cb(has_piof); + } + else + { + LLFloaterBuyCurrency::handleBuyCurrency(has_piof, mHasTarget, mName, mPrice); + } } } diff --git a/indra/newview/llfloaterbuycurrency.h b/indra/newview/llfloaterbuycurrency.h index 1b04c9c6d2..c6a80de926 100644 --- a/indra/newview/llfloaterbuycurrency.h +++ b/indra/newview/llfloaterbuycurrency.h @@ -30,21 +30,34 @@ #include "llavatarpropertiesprocessor.h" #include "stdtypes.h" #include "llagent.h" + +#include <functional> + class LLFloater; class LLFetchAvatarPaymentInfo : public LLAvatarPropertiesObserver { public: + typedef std::function<void(bool has_piof)> callback_t; + + // hands the result to LLFloaterBuyCurrency::handleBuyCurrency LLFetchAvatarPaymentInfo(bool has_target, const std::string& name = std::string(), S32 price = 0); + + // hands the result to cb, which may delete this observer + LLFetchAvatarPaymentInfo(const callback_t& cb); + ~LLFetchAvatarPaymentInfo(); void processProperties(void* data, EAvatarProcessorType type); private: + void sendRequest(); + LLUUID mAvatarID; bool mHasTarget; std::string mName; S32 mPrice; + callback_t mCallback; }; @@ -62,6 +75,9 @@ public: a space and the price will be appended */ + // open the LindeX page where a resident adds a payment method + static void openPaymentMethodPage(); + static LLFloater* buildFloater(const LLSD& key); static LLFetchAvatarPaymentInfo* sPropertiesRequest; |
