Creates a mojo channel between browser and renderer for Leo subscriptions on Android

This commit is contained in:
Serg
2023-12-15 07:30:33 -05:00
parent 6f4a13dff1
commit 284379d904
20 changed files with 338 additions and 53 deletions
@@ -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);
}
}
@@ -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);
+21
View File
@@ -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
+9 -2
View File
@@ -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",
@@ -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() {
@@ -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};
};
@@ -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");
@@ -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"),
+10 -1
View File
@@ -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);
}
+4 -1
View File
@@ -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) {