diff --git a/android/java/org/chromium/chrome/browser/settings/BraveLeoPreferences.java b/android/java/org/chromium/chrome/browser/settings/BraveLeoPreferences.java index 75764a437fb1..815f043c26a2 100644 --- a/android/java/org/chromium/chrome/browser/settings/BraveLeoPreferences.java +++ b/android/java/org/chromium/chrome/browser/settings/BraveLeoPreferences.java @@ -33,7 +33,7 @@ public class BraveLeoPreferences extends BravePreferenceFragment private static final String PREF_SUBSCRIPTION_CATEGORY = "subscription_category"; private static final String PREF_DEFAULT_MODEL = "default_model"; private static final String LINK_SUBSCRIPTION_URL = - "https://account.brave.com?intent=connect-receipt&product=leo"; + "https://account.brave.com?intent=link-order&product=leo"; @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { diff --git a/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.cc b/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.cc index ea94cf49c780..7ca953f78f22 100644 --- a/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.cc +++ b/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.cc @@ -27,8 +27,9 @@ AIChatIAPSubscription::AIChatIAPSubscription(PrefService* prefs) AIChatIAPSubscription::~AIChatIAPSubscription() = default; -void AIChatIAPSubscription::GetPurchaseToken( - GetPurchaseTokenCallback callback) { +void AIChatIAPSubscription::GetPurchaseTokenOrderId( + GetPurchaseTokenOrderIdCallback callback) { + std::string order_id_string = ""; std::string purchase_token_string = ""; std::string package_string = kDefaultPackage; std::string product_id_string = kProductId; @@ -52,6 +53,11 @@ void AIChatIAPSubscription::GetPurchaseToken( product_id_string = prefs_->GetString(prefs::kBraveChatProductIdAndroid); } + auto* order_id = prefs_->FindPreference(prefs::kBraveChatOrderIdAndroid); + if (order_id && !product_id->IsDefaultValue()) { + order_id_string = prefs_->GetString(prefs::kBraveChatOrderIdAndroid); + } + base::Value::Dict response; response.Set("type", "android"); response.Set("raw_receipt", purchase_token_string); @@ -63,7 +69,7 @@ void AIChatIAPSubscription::GetPurchaseToken( std::string encoded_response_json; base::Base64Encode(response_json, &encoded_response_json); - std::move(callback).Run(encoded_response_json); + std::move(callback).Run(encoded_response_json, order_id_string); } } // namespace ai_chat diff --git a/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.h b/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.h index bfc26384b0c0..7719ae549db6 100644 --- a/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.h +++ b/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.h @@ -24,7 +24,8 @@ class AIChatIAPSubscription final : public ai_chat::mojom::IAPSubscription { ~AIChatIAPSubscription() override; // ai_chat::mojom::IAPSubscription - void GetPurchaseToken(GetPurchaseTokenCallback callback) override; + void GetPurchaseTokenOrderId( + GetPurchaseTokenOrderIdCallback callback) override; private: raw_ptr prefs_ = nullptr; diff --git a/components/ai_chat/core/common/mojom/ai_chat.mojom b/components/ai_chat/core/common/mojom/ai_chat.mojom index ec87d299958d..3eaf1a4beb71 100644 --- a/components/ai_chat/core/common/mojom/ai_chat.mojom +++ b/components/ai_chat/core/common/mojom/ai_chat.mojom @@ -211,5 +211,5 @@ interface AIChatAndroidHelper { [EnableIf=is_android] interface IAPSubscription { - GetPurchaseToken() => (string token); + GetPurchaseTokenOrderId() => (string token, string order_id); }; diff --git a/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.cc b/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.cc index 71fdb3d3a3f9..64a6a57d9cbf 100644 --- a/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.cc +++ b/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.cc @@ -39,6 +39,7 @@ inline constexpr char kIntentParamTestValue[] = "connect-receipt-test"; inline constexpr char kProductParamName[] = "product"; inline constexpr char kProductVPNParamValue[] = "vpn"; inline constexpr char kProductLeoParamValue[] = "leo"; +inline constexpr char kIntentParamValueLeo[] = "link-order"; } // namespace @@ -61,8 +62,7 @@ bool SubscriptionRenderFrameObserver::EnsureConnected() { } #endif #if BUILDFLAG(ENABLE_AI_CHAT) - if (ai_chat::features::IsAIChatHistoryEnabled() && - product_ == Product::kLeo) { + if (ai_chat::features::IsAIChatEnabled() && product_ == Product::kLeo) { if (!ai_chat_subscription_.is_bound()) { render_frame()->GetBrowserInterfaceBroker()->GetInterface( ai_chat_subscription_.BindNewPipeAndPassReceiver()); @@ -105,14 +105,31 @@ void SubscriptionRenderFrameObserver::DidCreateScriptContext( } else if (product_ == Product::kLeo) { #if BUILDFLAG(ENABLE_AI_CHAT) if (ai_chat_subscription_.is_bound()) { - ai_chat_subscription_->GetPurchaseToken( - base::BindOnce(&SubscriptionRenderFrameObserver::OnGetPurchaseToken, - weak_factory_.GetWeakPtr())); + ai_chat_subscription_->GetPurchaseTokenOrderId(base::BindOnce( + &SubscriptionRenderFrameObserver::OnGetPurchaseTokenOrderId, + weak_factory_.GetWeakPtr())); } #endif } } +std::string SubscriptionRenderFrameObserver::GetPurchaseTokenJSString( + const std::string& purchase_token) { + if (!IsValueAllowed(purchase_token)) { + return ""; + } + + std::string_view receipt_var_name; + if (product_ == Product::kVPN) { + receipt_var_name = "braveVpn.receipt"; + } else if (product_ == Product::kLeo) { + receipt_var_name = "braveLeo.receipt"; + } + + return base::StrCat({"window.localStorage.setItem(\"", receipt_var_name, + "\", \"", purchase_token, "\");"}); +} + void SubscriptionRenderFrameObserver::OnGetPurchaseToken( const std::string& purchase_token) { if (!IsAllowed()) { @@ -120,21 +137,27 @@ void SubscriptionRenderFrameObserver::OnGetPurchaseToken( } auto* frame = render_frame(); if (frame) { - if (IsValueAllowed(purchase_token)) { - std::string_view receipt_var_name; - if (product_ == Product::kVPN) { - receipt_var_name = "braveVpn.receipt"; - } else if (product_ == Product::kLeo) { - receipt_var_name = "braveLeo.receipt"; - } - std::u16string set_local_storage = base::UTF8ToUTF16( - base::StrCat({"window.localStorage.setItem(\"", receipt_var_name, - "\", \"", purchase_token, "\");"})); - frame->ExecuteJavaScript(set_local_storage); + std::string set_local_storage = GetPurchaseTokenJSString(purchase_token); + if (!set_local_storage.empty()) { + frame->ExecuteJavaScript(base::UTF8ToUTF16(set_local_storage)); } } } +void SubscriptionRenderFrameObserver::OnGetPurchaseTokenOrderId( + const std::string& purchase_token, + const std::string& order_id) { + if (!IsAllowed()) { + return; + } + auto* frame = render_frame(); + if (frame && !order_id.empty() && !purchase_token.empty()) { + frame->ExecuteJavaScript(base::UTF8ToUTF16(base::StrCat( + {"window.localStorage.setItem(\"braveLeo.orderId\", \"", order_id, + "\");", GetPurchaseTokenJSString(purchase_token)}))); + } +} + std::string SubscriptionRenderFrameObserver::ExtractParam( const GURL& url, const std::string& name) const { @@ -182,7 +205,8 @@ bool SubscriptionRenderFrameObserver::IsAllowed() { } else { product_ = std::nullopt; } - return (intent == kIntentParamValue || intent == kIntentParamTestValue) && + return (intent == kIntentParamValue || intent == kIntentParamTestValue || + intent == kIntentParamValueLeo) && product_.has_value(); } diff --git a/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.h b/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.h index 5ea1ee63fed0..279bb094a291 100644 --- a/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.h +++ b/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.h @@ -59,6 +59,8 @@ class SubscriptionRenderFrameObserver : public content::RenderFrameObserver { bool EnsureConnected(); void OnGetPurchaseToken(const std::string& purchase_token); + void OnGetPurchaseTokenOrderId(const std::string& purchase_token, + const std::string& order_id); std::string ExtractParam(const GURL& url, const std::string& name) const; bool IsValueAllowed(const std::string& purchase_token) const; @@ -67,6 +69,8 @@ class SubscriptionRenderFrameObserver : public content::RenderFrameObserver { bool IsAllowed(); + std::string GetPurchaseTokenJSString(const std::string& purchase_token); + const int32_t world_id_; std::optional product_ = std::nullopt; #if BUILDFLAG(ENABLE_BRAVE_VPN) diff --git a/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer_browsertest.cc b/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer_browsertest.cc index 5733c1bcaf21..a18f7b342f1e 100644 --- a/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer_browsertest.cc +++ b/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer_browsertest.cc @@ -24,8 +24,8 @@ class SubscriptionRenderFrameObserverBrowserTest : SubscriptionRenderFrameObserverBrowserTest() { scoped_feature_list_.InitWithFeatures( {skus::features::kSkusFeature, brave_vpn::features::kBraveVPN, - ai_chat::features::kAIChatHistory - }, {}); + ai_chat::features::kAIChat}, + {}); } ~SubscriptionRenderFrameObserverBrowserTest() override = default; @@ -46,7 +46,7 @@ TEST_F(SubscriptionRenderFrameObserverBrowserTest, IsAllowed) { // Leo LoadHTMLWithUrlOverride( R"()", - "https://account.brave.com/?intent=connect-receipt&product=leo"); + "https://account.brave.com/?intent=link-order&product=leo"); EXPECT_TRUE(observer.IsAllowed()); // http