Creates a mojo channel between browser and renderer for Leo subscriptions on Android
This commit is contained in:
@@ -355,6 +355,7 @@ public class InAppPurchaseWrapper {
|
||||
if (isVPNProduct) {
|
||||
BraveVpnPrefUtils.setSubscriptionPurchase(true);
|
||||
} else if (isLeoProduct) {
|
||||
BraveLeoPrefUtils.setIsSubscriptionActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.jni_zero.JNINamespace;
|
||||
import org.jni_zero.NativeMethods;
|
||||
|
||||
import org.chromium.ai_chat.mojom.CredentialManagerHelper;
|
||||
import org.chromium.ai_chat.mojom.PremiumStatus;
|
||||
import org.chromium.content_public.browser.BrowserContextHandle;
|
||||
import org.chromium.mojo.bindings.ConnectionErrorHandler;
|
||||
import org.chromium.mojo.bindings.Interface;
|
||||
@@ -62,6 +63,7 @@ public class BraveLeoCMHelper implements ConnectionErrorHandler {
|
||||
|
||||
public void getPremiumStatus(CredentialManagerHelper.GetPremiumStatus_Response callback) {
|
||||
if (mCredentialManagerHelper == null) {
|
||||
callback.call(PremiumStatus.INACTIVE);
|
||||
return;
|
||||
}
|
||||
mCredentialManagerHelper.getPremiumStatus(callback);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.chromium.chrome.browser.brave_leo;
|
||||
|
||||
import org.chromium.base.ContextUtils;
|
||||
import org.chromium.base.Log;
|
||||
import org.chromium.chrome.browser.app.BraveActivity;
|
||||
import org.chromium.chrome.browser.preferences.BravePref;
|
||||
@@ -30,12 +31,52 @@ public class BraveLeoPrefUtils {
|
||||
}
|
||||
|
||||
public static void setIsSubscriptionActive(boolean value) {
|
||||
UserPrefs.get(BraveLeoPrefUtils.getProfile())
|
||||
Profile profileToUse = BraveLeoPrefUtils.getProfile();
|
||||
if (profileToUse == null) {
|
||||
Log.e(TAG, "BraveLeoPrefUtils.setIsSubscriptionActive profile is null");
|
||||
return;
|
||||
}
|
||||
UserPrefs.get(profileToUse)
|
||||
.setBoolean(BravePref.BRAVE_CHAT_SUBSCRIPTION_ACTIVE_ANDROID, value);
|
||||
}
|
||||
|
||||
public static boolean getIsSubscriptionActive(Profile profile) {
|
||||
return UserPrefs.get(profile == null ? BraveLeoPrefUtils.getProfile() : profile)
|
||||
Profile profileToUse = profile == null ? BraveLeoPrefUtils.getProfile() : profile;
|
||||
if (profileToUse == null) {
|
||||
Log.e(TAG, "BraveLeoPrefUtils.getIsSubscriptionActive profile is null");
|
||||
return false;
|
||||
}
|
||||
return UserPrefs.get(profileToUse)
|
||||
.getBoolean(BravePref.BRAVE_CHAT_SUBSCRIPTION_ACTIVE_ANDROID);
|
||||
}
|
||||
|
||||
public static void setChatPurchaseToken(String token) {
|
||||
Profile profileToUse = BraveLeoPrefUtils.getProfile();
|
||||
if (profileToUse == null) {
|
||||
Log.e(TAG, "BraveLeoPrefUtils.setChatPurchaseToken profile is null");
|
||||
return;
|
||||
}
|
||||
UserPrefs.get(profileToUse).setString(BravePref.BRAVE_CHAT_PURCHASE_TOKEN_ANDROID, token);
|
||||
}
|
||||
|
||||
public static void setChatPackageName() {
|
||||
Profile profileToUse = BraveLeoPrefUtils.getProfile();
|
||||
if (profileToUse == null) {
|
||||
Log.e(TAG, "BraveLeoPrefUtils.setChatPackageName profile is null");
|
||||
return;
|
||||
}
|
||||
UserPrefs.get(profileToUse)
|
||||
.setString(
|
||||
BravePref.BRAVE_CHAT_PACKAGE_NAME_ANDROID,
|
||||
ContextUtils.getApplicationContext().getPackageName());
|
||||
}
|
||||
|
||||
public static void setChatProductId(String productId) {
|
||||
Profile profileToUse = BraveLeoPrefUtils.getProfile();
|
||||
if (profileToUse == null) {
|
||||
Log.e(TAG, "BraveLeoPrefUtils.setChatProductId profile is null");
|
||||
return;
|
||||
}
|
||||
UserPrefs.get(profileToUse).setString(BravePref.BRAVE_CHAT_PRODUCT_ID_ANDROID, productId);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-7
@@ -5,9 +5,7 @@
|
||||
|
||||
package org.chromium.chrome.browser.brave_leo;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import org.jni_zero.CalledByNative;
|
||||
|
||||
@@ -31,11 +29,14 @@ public class BraveLeoSettingsLauncherHelper {
|
||||
|
||||
@CalledByNative
|
||||
private static void goPremium(WebContents webContents) {
|
||||
Activity activity = webContents.getTopLevelNativeWindow().getActivity().get();
|
||||
Intent braveLeoPlansIntent = new Intent(activity, BraveLeoPlansActivity.class);
|
||||
braveLeoPlansIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
braveLeoPlansIntent.setAction(Intent.ACTION_VIEW);
|
||||
activity.startActivity(braveLeoPlansIntent);
|
||||
// TODO(sergz): We need to uncomment that section when our backend can handle
|
||||
// mobile subscription. It's commented to avoid Purchase happens on Google Play Store
|
||||
|
||||
// Activity activity = webContents.getTopLevelNativeWindow().getActivity().get();
|
||||
// Intent braveLeoPlansIntent = new Intent(activity, BraveLeoPlansActivity.class);
|
||||
// braveLeoPlansIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
// braveLeoPlansIntent.setAction(Intent.ACTION_VIEW);
|
||||
// activity.startActivity(braveLeoPlansIntent);
|
||||
}
|
||||
|
||||
private static SettingsLauncher getLauncher() {
|
||||
|
||||
@@ -24,7 +24,12 @@ public class BraveLeoUtils {
|
||||
activePurchaseModel -> {
|
||||
BraveLeoPrefUtils.setIsSubscriptionActive(activePurchaseModel != null);
|
||||
if (activePurchaseModel != null) {
|
||||
BraveLeoPrefUtils.setChatPurchaseToken(
|
||||
activePurchaseModel.getPurchaseToken());
|
||||
BraveLeoPrefUtils.setChatPackageName();
|
||||
BraveLeoPrefUtils.setChatProductId(activePurchaseModel.getProductId());
|
||||
} else {
|
||||
// TODO(sergz): showRestoreMenu?
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.onResult(null);
|
||||
|
||||
@@ -154,6 +154,9 @@ using extensions::ChromeContentBrowserClientExtensionsPart;
|
||||
#include "brave/components/ai_chat/content/browser/ai_chat_throttle.h"
|
||||
#include "brave/components/ai_chat/core/common/features.h"
|
||||
#include "brave/components/ai_chat/core/common/mojom/ai_chat.mojom.h"
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
#include "brave/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_BRAVE_WEBTORRENT)
|
||||
@@ -449,6 +452,18 @@ void BindBraveSearchDefaultHost(
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
void BindIAPSubscription(
|
||||
content::RenderFrameHost* const frame_host,
|
||||
mojo::PendingReceiver<ai_chat::mojom::IAPSubscription> receiver) {
|
||||
auto* context = frame_host->GetBrowserContext();
|
||||
auto* profile = Profile::FromBrowserContext(context);
|
||||
mojo::MakeSelfOwnedReceiver(
|
||||
std::make_unique<ai_chat::AIChatIAPSubscription>(profile->GetPrefs()),
|
||||
std::move(receiver));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
void MaybeBindBraveVpnImpl(
|
||||
content::RenderFrameHost* const frame_host,
|
||||
@@ -743,6 +758,12 @@ void BraveContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
|
||||
content::RegisterWebUIControllerInterfaceBinder<ai_chat::mojom::PageHandler,
|
||||
AIChatUI>(map);
|
||||
}
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
if (ai_chat::features::IsAIChatEnabled()) {
|
||||
map->Add<ai_chat::mojom::IAPSubscription>(
|
||||
base::BindRepeating(&BindIAPSubscription));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Brave News
|
||||
|
||||
@@ -4110,7 +4110,7 @@ If you don't accept this request, VPN will not reconnect and your internet conne
|
||||
Manage Subscription
|
||||
</message>
|
||||
<message name="IDS_BRAVE_LEO_PREMIUM" desc="Title for Brave Leo plans dialog">
|
||||
Leo Premium
|
||||
Leo Premium
|
||||
</message>
|
||||
<message name="IDS_MONTHLY_SUBSCRIPTION_LEO" desc="Brave Leo plan text">
|
||||
Monthly subscription
|
||||
|
||||
@@ -11,14 +11,14 @@ static_library("browser") {
|
||||
sources = [
|
||||
"ai_chat_credential_manager.cc",
|
||||
"ai_chat_credential_manager.h",
|
||||
"conversation_driver.cc",
|
||||
"conversation_driver.h",
|
||||
"ai_chat_feedback_api.cc",
|
||||
"ai_chat_feedback_api.h",
|
||||
"ai_chat_metrics.cc",
|
||||
"ai_chat_metrics.h",
|
||||
"constants.cc",
|
||||
"constants.h",
|
||||
"conversation_driver.cc",
|
||||
"conversation_driver.h",
|
||||
"engine/engine_consumer.h",
|
||||
"engine/engine_consumer_claude.cc",
|
||||
"engine/engine_consumer_claude.h",
|
||||
@@ -30,6 +30,13 @@ static_library("browser") {
|
||||
"models.h",
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
sources += [
|
||||
"android/ai_chat_iap_subscription_android.cc",
|
||||
"android/ai_chat_iap_subscription_android.h",
|
||||
]
|
||||
}
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//brave/brave_domains",
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/* Copyright (c) 2023 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/ai_chat/core/browser/android/ai_chat_iap_subscription_android.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/base64.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "brave/components/ai_chat/core/common/pref_names.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
|
||||
namespace {
|
||||
|
||||
inline constexpr char kDefaultPackage[] = "com.brave.browser";
|
||||
inline constexpr char kProductId[] = "brave.leo.monthly";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace ai_chat {
|
||||
|
||||
AIChatIAPSubscription::AIChatIAPSubscription(PrefService* prefs)
|
||||
: prefs_(prefs) {}
|
||||
|
||||
AIChatIAPSubscription::~AIChatIAPSubscription() = default;
|
||||
|
||||
void AIChatIAPSubscription::GetPurchaseToken(
|
||||
GetPurchaseTokenCallback callback) {
|
||||
std::string purchase_token_string = "";
|
||||
std::string package_string = kDefaultPackage;
|
||||
std::string product_id_string = kProductId;
|
||||
|
||||
// Get the Android purchase token (for Google Play Store).
|
||||
// The value for this is validated on the account.brave.com side
|
||||
auto* purchase_token =
|
||||
prefs_->FindPreference(prefs::kBraveChatPurchaseTokenAndroid);
|
||||
if (purchase_token && !purchase_token->IsDefaultValue()) {
|
||||
purchase_token_string =
|
||||
prefs_->GetString(prefs::kBraveChatPurchaseTokenAndroid);
|
||||
}
|
||||
|
||||
auto* package = prefs_->FindPreference(prefs::kBraveChatPackageNameAndroid);
|
||||
if (package && !package->IsDefaultValue()) {
|
||||
package_string = prefs_->GetString(prefs::kBraveChatPackageNameAndroid);
|
||||
}
|
||||
|
||||
auto* product_id = prefs_->FindPreference(prefs::kBraveChatProductIdAndroid);
|
||||
if (product_id && !product_id->IsDefaultValue()) {
|
||||
product_id_string = prefs_->GetString(prefs::kBraveChatProductIdAndroid);
|
||||
}
|
||||
|
||||
base::Value::Dict response;
|
||||
response.Set("type", "android");
|
||||
response.Set("raw_receipt", purchase_token_string);
|
||||
response.Set("package", package_string);
|
||||
response.Set("subscription_id", product_id_string);
|
||||
|
||||
std::string response_json;
|
||||
base::JSONWriter::Write(response, &response_json);
|
||||
|
||||
std::string encoded_response_json;
|
||||
base::Base64Encode(response_json, &encoded_response_json);
|
||||
std::move(callback).Run(encoded_response_json);
|
||||
}
|
||||
|
||||
} // namespace ai_chat
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Copyright (c) 2023 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_COMPONENTS_AI_CHAT_CORE_BROWSER_ANDROID_AI_CHAT_IAP_SUBSCRIPTION_ANDROID_H_
|
||||
#define BRAVE_COMPONENTS_AI_CHAT_CORE_BROWSER_ANDROID_AI_CHAT_IAP_SUBSCRIPTION_ANDROID_H_
|
||||
|
||||
#include "brave/components/ai_chat/core/common/mojom/ai_chat.mojom.h"
|
||||
|
||||
class PrefService;
|
||||
|
||||
namespace ai_chat {
|
||||
|
||||
// AIChatIAPSubscription is a class that is responsible for interaction
|
||||
// between SubscriptionRenderFrameObserver class that lives inside renderer
|
||||
// process.
|
||||
|
||||
class AIChatIAPSubscription final : public ai_chat::mojom::IAPSubscription {
|
||||
public:
|
||||
AIChatIAPSubscription(const AIChatIAPSubscription&) = delete;
|
||||
AIChatIAPSubscription& operator=(const AIChatIAPSubscription&) = delete;
|
||||
explicit AIChatIAPSubscription(PrefService* prefs);
|
||||
~AIChatIAPSubscription() override;
|
||||
|
||||
// ai_chat::mojom::IAPSubscription
|
||||
void GetPurchaseToken(GetPurchaseTokenCallback callback) override;
|
||||
|
||||
private:
|
||||
raw_ptr<PrefService> prefs_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ai_chat
|
||||
|
||||
#endif // BRAVE_COMPONENTS_AI_CHAT_CORE_BROWSER_ANDROID_AI_CHAT_IAP_SUBSCRIPTION_ANDROID_H_
|
||||
@@ -164,3 +164,8 @@ interface ChatUIPage {
|
||||
interface CredentialManagerHelper {
|
||||
GetPremiumStatus() => (PremiumStatus result);
|
||||
};
|
||||
|
||||
[EnableIf=is_android]
|
||||
interface IAPSubscription {
|
||||
GetPurchaseToken() => (string token);
|
||||
};
|
||||
|
||||
@@ -24,6 +24,9 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
|
||||
registry->RegisterStringPref(kDefaultModelKey, "chat-default");
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
registry->RegisterBooleanPref(kBraveChatSubscriptionActiveAndroid, false);
|
||||
registry->RegisterStringPref(kBraveChatPurchaseTokenAndroid, "");
|
||||
registry->RegisterStringPref(kBraveChatPackageNameAndroid, "");
|
||||
registry->RegisterStringPref(kBraveChatProductIdAndroid, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ inline constexpr char kBraveChatP3ALastPremiumStatus[] =
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
inline constexpr char kBraveChatSubscriptionActiveAndroid[] =
|
||||
"brave.ai_chat.subscription_active_android";
|
||||
inline constexpr char kBraveChatPurchaseTokenAndroid[] =
|
||||
"brave.ai_chat.purchase_token_android";
|
||||
inline constexpr char kBraveChatPackageNameAndroid[] =
|
||||
"brave.ai_chat.package_name_android";
|
||||
inline constexpr char kBraveChatProductIdAndroid[] =
|
||||
"brave.ai_chat.product_id_android";
|
||||
#endif
|
||||
|
||||
void RegisterProfilePrefs(PrefRegistrySimple* registry);
|
||||
|
||||
@@ -17,9 +17,8 @@ source_set("android") {
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//brave/components/brave_vpn/common",
|
||||
"//brave/components/ai_chat/core/common/buildflags",
|
||||
"//brave/components/brave_vpn/common/buildflags",
|
||||
"//brave/components/brave_vpn/common/mojom",
|
||||
"//brave/components/skus/renderer",
|
||||
"//content/public/renderer",
|
||||
"//gin",
|
||||
@@ -29,6 +28,19 @@ source_set("android") {
|
||||
"//third_party/blink/public/strings",
|
||||
"//v8",
|
||||
]
|
||||
|
||||
if (enable_ai_chat) {
|
||||
deps += [
|
||||
"//brave/components/ai_chat/core/common",
|
||||
"//brave/components/ai_chat/core/common/mojom",
|
||||
]
|
||||
}
|
||||
if (enable_brave_vpn) {
|
||||
deps += [
|
||||
"//brave/components/brave_vpn/common",
|
||||
"//brave/components/brave_vpn/common/mojom",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("browser_tests") {
|
||||
@@ -39,6 +51,8 @@ source_set("browser_tests") {
|
||||
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
|
||||
|
||||
deps = [
|
||||
"//brave/components/ai_chat/core/common",
|
||||
"//brave/components/ai_chat/core/common/buildflags",
|
||||
"//brave/components/brave_vpn/common",
|
||||
"//brave/components/brave_vpn/common/buildflags:buildflags",
|
||||
"//brave/components/brave_mobile_subscription/renderer/android",
|
||||
|
||||
+63
-23
@@ -25,15 +25,20 @@
|
||||
#include "brave/components/brave_vpn/common/brave_vpn_utils.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT)
|
||||
#include "brave/components/ai_chat/core/common/features.h"
|
||||
#endif
|
||||
|
||||
namespace brave_subscription {
|
||||
|
||||
namespace {
|
||||
|
||||
char kIntentParamName[] = "intent";
|
||||
char kIntentParamValue[] = "connect-receipt";
|
||||
char kIntentParamTestValue[] = "connect-receipt-test";
|
||||
char kProductParamName[] = "product";
|
||||
char kProductParamValue[] = "vpn";
|
||||
inline constexpr char kIntentParamName[] = "intent";
|
||||
inline constexpr char kIntentParamValue[] = "connect-receipt";
|
||||
inline constexpr char kIntentParamTestValue[] = "connect-receipt-test";
|
||||
inline constexpr char kProductParamName[] = "product";
|
||||
inline constexpr char kProductVPNParamValue[] = "vpn";
|
||||
inline constexpr char kProductLeoParamValue[] = "leo";
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -47,11 +52,23 @@ SubscriptionRenderFrameObserver::~SubscriptionRenderFrameObserver() = default;
|
||||
bool SubscriptionRenderFrameObserver::EnsureConnected() {
|
||||
bool bound = false;
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
if (!vpn_service_.is_bound()) {
|
||||
render_frame()->GetBrowserInterfaceBroker()->GetInterface(
|
||||
vpn_service_.BindNewPipeAndPassReceiver());
|
||||
if (brave_vpn::IsBraveVPNFeatureEnabled() && product_ == Product::kVPN) {
|
||||
if (!vpn_service_.is_bound()) {
|
||||
render_frame()->GetBrowserInterfaceBroker()->GetInterface(
|
||||
vpn_service_.BindNewPipeAndPassReceiver());
|
||||
}
|
||||
bound |= vpn_service_.is_bound();
|
||||
}
|
||||
#endif
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT)
|
||||
if (ai_chat::features::IsAIChatHistoryEnabled() &&
|
||||
product_ == Product::kLeo) {
|
||||
if (!ai_chat_subscription_.is_bound()) {
|
||||
render_frame()->GetBrowserInterfaceBroker()->GetInterface(
|
||||
ai_chat_subscription_.BindNewPipeAndPassReceiver());
|
||||
}
|
||||
bound |= ai_chat_subscription_.is_bound();
|
||||
}
|
||||
bound = vpn_service_.is_bound();
|
||||
#endif
|
||||
return bound;
|
||||
}
|
||||
@@ -67,17 +84,33 @@ void SubscriptionRenderFrameObserver::DidCreateScriptContext(
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(product_.has_value());
|
||||
if (!product_.has_value()) {
|
||||
return;
|
||||
}
|
||||
auto connected = EnsureConnected();
|
||||
if (!connected) {
|
||||
LOG(ERROR) << "Failed to establish connection to BraveVpnService";
|
||||
LOG(ERROR) << "Failed to establish connection to a mojo channel";
|
||||
return;
|
||||
}
|
||||
|
||||
if (product_ == Product::kVPN) {
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
vpn_service_->GetPurchaseToken(base::BindOnce(
|
||||
&SubscriptionRenderFrameObserver::OnGetPurchaseToken,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
if (vpn_service_.is_bound()) {
|
||||
vpn_service_->GetPurchaseToken(
|
||||
base::BindOnce(&SubscriptionRenderFrameObserver::OnGetPurchaseToken,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
#endif
|
||||
} 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()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void SubscriptionRenderFrameObserver::OnGetPurchaseToken(
|
||||
@@ -88,11 +121,15 @@ void SubscriptionRenderFrameObserver::OnGetPurchaseToken(
|
||||
auto* frame = render_frame();
|
||||
if (frame) {
|
||||
if (IsValueAllowed(purchase_token)) {
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
std::u16string set_local_storage =
|
||||
base::StrCat({u"window.localStorage.setItem(\"braveVpn.receipt\", \"",
|
||||
base::UTF8ToUTF16(purchase_token), u"\");"});
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -129,10 +166,6 @@ bool SubscriptionRenderFrameObserver::IsValueAllowed(
|
||||
}
|
||||
|
||||
bool SubscriptionRenderFrameObserver::IsAllowed() {
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
DCHECK(brave_vpn::IsBraveVPNFeatureEnabled());
|
||||
#endif
|
||||
|
||||
if (!skus::IsSafeOrigin(render_frame()->GetWebFrame()->GetSecurityOrigin())) {
|
||||
return false;
|
||||
}
|
||||
@@ -142,8 +175,15 @@ bool SubscriptionRenderFrameObserver::IsAllowed() {
|
||||
|
||||
std::string intent = ExtractParam(current_url, kIntentParamName);
|
||||
std::string product = ExtractParam(current_url, kProductParamName);
|
||||
if (product == kProductVPNParamValue) {
|
||||
product_ = Product::kVPN;
|
||||
} else if (product == kProductLeoParamValue) {
|
||||
product_ = Product::kLeo;
|
||||
} else {
|
||||
product_ = std::nullopt;
|
||||
}
|
||||
return (intent == kIntentParamValue || intent == kIntentParamTestValue) &&
|
||||
product == kProductParamValue;
|
||||
product_.has_value();
|
||||
}
|
||||
|
||||
void SubscriptionRenderFrameObserver::OnDestruct() {
|
||||
|
||||
+16
-6
@@ -7,10 +7,12 @@
|
||||
#define BRAVE_COMPONENTS_BRAVE_MOBILE_SUBSCRIPTION_RENDERER_ANDROID_SUBSCRIPTION_RENDER_FRAME_OBSERVER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "brave/components/ai_chat/core/common/buildflags/buildflags.h"
|
||||
#include "brave/components/brave_vpn/common/buildflags/buildflags.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "content/public/renderer/render_frame_observer.h"
|
||||
@@ -20,6 +22,9 @@
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
#include "brave/components/brave_vpn/common/mojom/brave_vpn.mojom.h"
|
||||
#endif
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT)
|
||||
#include "brave/components/ai_chat/core/common/mojom/ai_chat.mojom.h"
|
||||
#endif
|
||||
|
||||
namespace brave_subscription {
|
||||
|
||||
@@ -34,11 +39,11 @@ namespace brave_subscription {
|
||||
class SubscriptionRenderFrameObserver : public content::RenderFrameObserver {
|
||||
public:
|
||||
explicit SubscriptionRenderFrameObserver(content::RenderFrame* render_frame,
|
||||
int32_t world_id);
|
||||
SubscriptionRenderFrameObserver(
|
||||
const SubscriptionRenderFrameObserver&) = delete;
|
||||
int32_t world_id);
|
||||
SubscriptionRenderFrameObserver(const SubscriptionRenderFrameObserver&) =
|
||||
delete;
|
||||
SubscriptionRenderFrameObserver& operator=(
|
||||
const SubscriptionRenderFrameObserver&) = delete;
|
||||
const SubscriptionRenderFrameObserver&) = delete;
|
||||
~SubscriptionRenderFrameObserver() override;
|
||||
|
||||
// RenderFrameObserver implementation.
|
||||
@@ -47,9 +52,10 @@ class SubscriptionRenderFrameObserver : public content::RenderFrameObserver {
|
||||
|
||||
private:
|
||||
FRIEND_TEST_ALL_PREFIXES(SubscriptionRenderFrameObserverBrowserTest,
|
||||
IsAllowed);
|
||||
IsAllowed);
|
||||
FRIEND_TEST_ALL_PREFIXES(SubscriptionRenderFrameObserverTest, ExtractParam);
|
||||
FRIEND_TEST_ALL_PREFIXES(SubscriptionRenderFrameObserverTest, IsValueAllowed);
|
||||
enum class Product { kVPN = 0, kLeo = 1 };
|
||||
|
||||
bool EnsureConnected();
|
||||
void OnGetPurchaseToken(const std::string& purchase_token);
|
||||
@@ -61,9 +67,13 @@ class SubscriptionRenderFrameObserver : public content::RenderFrameObserver {
|
||||
|
||||
bool IsAllowed();
|
||||
|
||||
int32_t world_id_;
|
||||
const int32_t world_id_;
|
||||
std::optional<Product> product_ = std::nullopt;
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
mojo::Remote<brave_vpn::mojom::ServiceHandler> vpn_service_;
|
||||
#endif
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT)
|
||||
mojo::Remote<ai_chat::mojom::IAPSubscription> ai_chat_subscription_;
|
||||
#endif
|
||||
base::WeakPtrFactory<SubscriptionRenderFrameObserver> weak_factory_{this};
|
||||
};
|
||||
|
||||
+16
-8
@@ -6,8 +6,10 @@
|
||||
#include "brave/components/brave_mobile_subscription/renderer/android/subscription_render_frame_observer.h"
|
||||
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "brave/components/brave_vpn/common/buildflags/buildflags.h"
|
||||
#include "brave/components/ai_chat/core/common/features.h"
|
||||
#include "brave/components/ai_chat/core/common/buildflags/buildflags.h"
|
||||
#include "brave/components/brave_vpn/common/features.h"
|
||||
#include "brave/components/brave_vpn/common/buildflags/buildflags.h"
|
||||
#include "brave/components/skus/common/features.h"
|
||||
#include "content/public/common/isolated_world_ids.h"
|
||||
#include "content/public/test/content_mock_cert_verifier.h"
|
||||
@@ -21,10 +23,8 @@ class SubscriptionRenderFrameObserverBrowserTest :
|
||||
public:
|
||||
SubscriptionRenderFrameObserverBrowserTest() {
|
||||
scoped_feature_list_.InitWithFeatures(
|
||||
{skus::features::kSkusFeature
|
||||
#if BUILDFLAG(ENABLE_BRAVE_VPN)
|
||||
, brave_vpn::features::kBraveVPN
|
||||
#endif
|
||||
{skus::features::kSkusFeature, brave_vpn::features::kBraveVPN,
|
||||
ai_chat::features::kAIChatHistory
|
||||
}, {});
|
||||
}
|
||||
~SubscriptionRenderFrameObserverBrowserTest() override = default;
|
||||
@@ -36,10 +36,18 @@ class SubscriptionRenderFrameObserverBrowserTest :
|
||||
TEST_F(SubscriptionRenderFrameObserverBrowserTest, IsAllowed) {
|
||||
SubscriptionRenderFrameObserver observer(GetMainRenderFrame(),
|
||||
content::ISOLATED_WORLD_ID_GLOBAL);
|
||||
// VPN
|
||||
LoadHTMLWithUrlOverride(
|
||||
R"(<html><body></body></html>)",
|
||||
"https://account.brave.com/?intent=connect-receipt&product=vpn");
|
||||
|
||||
EXPECT_TRUE(observer.IsAllowed());
|
||||
|
||||
// Leo
|
||||
LoadHTMLWithUrlOverride(
|
||||
R"(<html><body></body></html>)",
|
||||
"https://account.brave.com/?intent=connect-receipt&product=leo");
|
||||
|
||||
EXPECT_TRUE(observer.IsAllowed());
|
||||
// http
|
||||
LoadHTMLWithUrlOverride(
|
||||
@@ -62,20 +70,20 @@ TEST_F(SubscriptionRenderFrameObserverBrowserTest, IsAllowed) {
|
||||
|
||||
EXPECT_TRUE(observer.IsAllowed());
|
||||
|
||||
// no recepit
|
||||
// no receipt
|
||||
LoadHTMLWithUrlOverride(
|
||||
R"(<html><body></body></html>)",
|
||||
"https://account.brave.software/?intent=&product=vpn");
|
||||
|
||||
EXPECT_FALSE(observer.IsAllowed());
|
||||
|
||||
// wrong recepit
|
||||
// wrong receipt
|
||||
LoadHTMLWithUrlOverride(R"(<html><body></body></html>)",
|
||||
"https://account.brave.software/?product=vpn");
|
||||
|
||||
EXPECT_FALSE(observer.IsAllowed());
|
||||
|
||||
// wrong recepit
|
||||
// wrong receipt
|
||||
LoadHTMLWithUrlOverride(
|
||||
R"(<html><body></body></html>)",
|
||||
"https://account.brave.software/?intent=wrong&product=vpn");
|
||||
|
||||
+5
@@ -27,6 +27,11 @@ TEST(SubscriptionRenderFrameObserverTest, ExtractParam) {
|
||||
GURL("https://account.brave.com/?intent=connect-receipt&product=vpn"),
|
||||
"product"),
|
||||
"vpn");
|
||||
EXPECT_EQ(
|
||||
observer.ExtractParam(
|
||||
GURL("https://account.brave.com/?intent=connect-receipt&product=leo"),
|
||||
"product"),
|
||||
"leo");
|
||||
EXPECT_TRUE(observer
|
||||
.ExtractParam(GURL("https://account.brave.com/"
|
||||
"?intent=connect-receipt&product=vpn"),
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/feature_list.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
#include "brave/components/ai_chat/core/common/buildflags/buildflags.h"
|
||||
#include "brave/components/brave_search/common/brave_search_utils.h"
|
||||
#include "brave/components/brave_search/renderer/brave_search_render_frame_observer.h"
|
||||
#include "brave/components/brave_shields/common/features.h"
|
||||
@@ -56,6 +57,10 @@
|
||||
#include "third_party/widevine/cdm/widevine_cdm_common.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT) && BUILDFLAG(IS_ANDROID)
|
||||
#include "brave/components/ai_chat/core/common/features.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
void MaybeRemoveWidevineSupport(media::GetSupportedKeySystemsCB cb,
|
||||
media::KeySystemInfos key_systems) {
|
||||
@@ -153,7 +158,11 @@ void BraveContentRendererClient::RenderFrameCreated(
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
if (brave_vpn::IsBraveVPNFeatureEnabled()) {
|
||||
if (brave_vpn::IsBraveVPNFeatureEnabled()
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT)
|
||||
|| ai_chat::features::IsAIChatHistoryEnabled()
|
||||
#endif
|
||||
) {
|
||||
new brave_subscription::SubscriptionRenderFrameObserver(
|
||||
render_frame, content::ISOLATED_WORLD_ID_GLOBAL);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,10 @@ if (enable_speedreader) {
|
||||
}
|
||||
|
||||
if (enable_ai_chat) {
|
||||
brave_chrome_renderer_deps += [ "//brave/components/ai_chat/renderer" ]
|
||||
brave_chrome_renderer_deps += [
|
||||
"//brave/components/ai_chat/core/common:common",
|
||||
"//brave/components/ai_chat/renderer",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_playlist) {
|
||||
|
||||
Reference in New Issue
Block a user