Skip to content

Commit

Permalink
AI Chat becomes a trusted WebUI with an UntrustedWebUI frame for LLM-…
Browse files Browse the repository at this point in the history
…generated responses (#26855)

* AI Chat becomes a trusted WebUI with an UntrustedWebUI frame for LLM-generated responses

- changes Leo Url to chrome://leo-ai
- untrusted frame content Url is chrome-untrusted://leo-ai-conversation-entries

They use the same JS build to optimize bundle size, but do not share the same allowed mojom interfaces. The untrusted frame is limited to UntrustedConversationHandler to send calls to the browser and UntrustedConversationUI to receive calls from the browser.
  • Loading branch information
petemill authored Dec 12, 2024
1 parent 750933f commit 2fc11a2
Show file tree
Hide file tree
Showing 103 changed files with 1,941 additions and 844 deletions.
3 changes: 3 additions & 0 deletions browser/ai_chat/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ static_library("ai_chat") {
"ai_chat_service_factory.h",
"ai_chat_settings_helper.cc",
"ai_chat_settings_helper.h",
"ai_chat_urls.cc",
"ai_chat_urls.h",
"ai_chat_utils.cc",
"ai_chat_utils.h",
]
Expand All @@ -24,6 +26,7 @@ static_library("ai_chat") {
"//brave/components/ai_chat/core/browser",
"//brave/components/ai_chat/core/common",
"//brave/components/ai_chat/core/common/mojom",
"//brave/components/constants",
"//brave/components/resources:strings_grit",
"//brave/net/base:utils",
"//chrome/browser:browser_process",
Expand Down
33 changes: 30 additions & 3 deletions browser/ai_chat/ai_chat_throttle_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
* 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/content/browser/ai_chat_throttle.h"

#include <memory>

#include "base/test/scoped_feature_list.h"
#include "brave/components/ai_chat/content/browser/ai_chat_throttle.h"
#include "brave/components/ai_chat/core/common/features.h"
#include "brave/components/constants/webui_url_constants.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
Expand All @@ -20,7 +22,9 @@
namespace ai_chat {

namespace {

constexpr char kTestProfileName[] = "TestProfile";

} // namespace

class AiChatThrottleUnitTest : public testing::Test,
Expand Down Expand Up @@ -73,7 +77,7 @@ INSTANTIATE_TEST_SUITE_P(
TEST_P(AiChatThrottleUnitTest, CancelNavigationFromTab) {
content::MockNavigationHandle test_handle(web_contents());

test_handle.set_url(GURL("chrome-untrusted://chat"));
test_handle.set_url(GURL(kAIChatUIURL));

#if BUILDFLAG(IS_ANDROID)
ui::PageTransition transition = ui::PageTransitionFromInt(
Expand All @@ -98,10 +102,33 @@ TEST_P(AiChatThrottleUnitTest, CancelNavigationFromTab) {
}
}

TEST_P(AiChatThrottleUnitTest, CancelNavigationToFrame) {
content::MockNavigationHandle test_handle(web_contents());

test_handle.set_url(GURL(kAIChatUntrustedConversationUIURL));

#if BUILDFLAG(IS_ANDROID)
ui::PageTransition transition = ui::PageTransitionFromInt(
ui::PageTransition::PAGE_TRANSITION_FROM_ADDRESS_BAR);
#else
ui::PageTransition transition = ui::PageTransitionFromInt(
ui::PageTransition::PAGE_TRANSITION_FROM_ADDRESS_BAR |
ui::PageTransition::PAGE_TRANSITION_TYPED);
#endif

test_handle.set_page_transition(transition);

std::unique_ptr<AiChatThrottle> throttle =
AiChatThrottle::MaybeCreateThrottleFor(&test_handle);

EXPECT_EQ(content::NavigationThrottle::CANCEL_AND_IGNORE,
throttle->WillStartRequest().action());
}

TEST_P(AiChatThrottleUnitTest, AllowNavigationFromPanel) {
content::MockNavigationHandle test_handle(web_contents());

test_handle.set_url(GURL("chrome-untrusted://chat"));
test_handle.set_url(GURL(kAIChatUIURL));

#if BUILDFLAG(IS_ANDROID)
ui::PageTransition transition =
Expand Down
29 changes: 29 additions & 0 deletions browser/ai_chat/ai_chat_urls.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2024 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/browser/ai_chat/ai_chat_urls.h"

#include <string_view>

#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "brave/components/constants/webui_url_constants.h"
#include "url/gurl.h"

namespace ai_chat {

GURL TabAssociatedConversationUrl() {
return GURL(base::StrCat({kAIChatUIURL, "tab"}));
}

GURL ConversationUrl(std::string_view conversation_uuid) {
return GURL(base::StrCat({kAIChatUIURL, conversation_uuid}));
}

std::string_view ConversationUUIDFromURL(const GURL& url) {
return base::TrimString(url.path_piece(), "/", base::TrimPositions::TRIM_ALL);
}

} // namespace ai_chat
29 changes: 29 additions & 0 deletions browser/ai_chat/ai_chat_urls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2024 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_BROWSER_AI_CHAT_AI_CHAT_URLS_H_
#define BRAVE_BROWSER_AI_CHAT_AI_CHAT_URLS_H_

#include <string_view>

#include "url/gurl.h"

namespace ai_chat {

// UI that will open a conversation associated with the active Tab in the same
// browser window. The conversation will change when that Tab navigates.
GURL TabAssociatedConversationUrl();

// UI that will open to a specific conversation. The conversation will not
// change upon any navigation.
GURL ConversationUrl(std::string_view conversation_uuid);

// Extracts the conversation UUID from a conversation URL or a conversation
// entries iframe
std::string_view ConversationUUIDFromURL(const GURL& url);

} // namespace ai_chat

#endif // BRAVE_BROWSER_AI_CHAT_AI_CHAT_URLS_H_
5 changes: 3 additions & 2 deletions browser/ai_chat/android/ai_chat_utils_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "base/android/jni_string.h"
#include "base/time/time.h"
#include "brave/browser/ai_chat/ai_chat_service_factory.h"
#include "brave/browser/ai_chat/ai_chat_urls.h"
#include "brave/build/android/jni_headers/BraveLeoUtils_jni.h"
#include "brave/components/ai_chat/content/browser/ai_chat_tab_helper.h"
#include "brave/components/ai_chat/core/browser/ai_chat_service.h"
Expand Down Expand Up @@ -55,7 +56,7 @@ static void JNI_BraveLeoUtils_OpenLeoQuery(
conversation->SubmitHumanConversationEntry(std::move(turn));

content::OpenURLParams params(
GURL(base::StrCat({kChatUIURL, conversation->get_conversation_uuid()})),
ConversationUrl(conversation->get_conversation_uuid()),
content::Referrer(), WindowOpenDisposition::CURRENT_TAB,
ui::PAGE_TRANSITION_FROM_API, false);
web_contents->OpenURL(params, {});
Expand All @@ -77,7 +78,7 @@ static void JNI_BraveLeoUtils_OpenLeoUrlForTab(
chat_tab_helper->GetContentId(), chat_tab_helper->GetWeakPtr());

content::OpenURLParams params(
GURL(base::StrCat({kChatUIURL, conversation->get_conversation_uuid()})),
ConversationUrl(conversation->get_conversation_uuid()),
content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui::PAGE_TRANSITION_FROM_API, false);
web_contents->OpenURL(params, {});
Expand Down
5 changes: 5 additions & 0 deletions browser/brave_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "brave/browser/ui/brave_ui_features.h"
#include "brave/browser/ui/webui/ads_internals/ads_internals_ui.h"
#include "brave/browser/ui/webui/ai_chat/ai_chat_ui.h"
#include "brave/browser/ui/webui/ai_chat/ai_chat_untrusted_conversation_ui.h"
#include "brave/browser/ui/webui/brave_rewards/rewards_page_ui.h"
#include "brave/browser/ui/webui/skus_internals_ui.h"
#include "brave/browser/url_sanitizer/url_sanitizer_service_factory.h"
Expand All @@ -50,6 +51,7 @@
#include "brave/components/ai_chat/core/common/mojom/ai_chat.mojom.h"
#include "brave/components/ai_chat/core/common/mojom/page_content_extractor.mojom.h"
#include "brave/components/ai_chat/core/common/mojom/settings_helper.mojom.h"
#include "brave/components/ai_chat/core/common/mojom/untrusted_frame.mojom.h"
#include "brave/components/ai_rewriter/common/buildflags/buildflags.h"
#include "brave/components/body_sniffer/body_sniffer_throttle.h"
#include "brave/components/brave_federated/features.h"
Expand Down Expand Up @@ -622,6 +624,9 @@ void BraveContentBrowserClient::RegisterWebUIInterfaceBrokers(
registry.ForWebUI<AIChatUI>()
.Add<ai_chat::mojom::AIChatUIHandler>()
.Add<ai_chat::mojom::Service>();
registry.ForWebUI<AIChatUntrustedConversationUI>()
.Add<ai_chat::mojom::UntrustedUIHandler>()
.Add<ai_chat::mojom::UntrustedConversationHandler>();
}

#if BUILDFLAG(ENABLE_AI_REWRITER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ RegisterPolymerTemplateModifications({
// Add leo item
const leoAssistantEl = createMenuElement(
loadTimeData.getString('leoAssistant'),
'/leo-assistant',
'/leo-ai',
'product-brave-leo',
'leoAssistant',
)
Expand Down
2 changes: 1 addition & 1 deletion browser/resources/settings/brave_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default function addBraveRoutes(r: Partial<SettingsRoutes>) {

if (pageVisibility.leoAssistant) {
r.BRAVE_LEO_ASSISTANT =
r.BASIC.createSection('/leo-assistant', 'leoAssistant')
r.BASIC.createSection('/leo-ai', 'leoAssistant')
}
if (pageVisibility.content) {
r.BRAVE_CONTENT = r.BASIC.createSection('/braveContent', 'content')
Expand Down
1 change: 1 addition & 0 deletions browser/resources/settings/sources.gni
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ brave_settings_ts_extra_deps =
brave_settings_mojo_files = [
"$root_gen_dir/brave/components/ai_chat/core/common/mojom/settings_helper.mojom-webui.ts",
"$root_gen_dir/brave/components/ai_chat/core/common/mojom/ai_chat.mojom-webui.ts",
"$root_gen_dir/brave/components/ai_chat/core/common/mojom/untrusted_frame.mojom-webui.ts",
]

brave_settings_mojo_files_deps =
Expand Down
4 changes: 3 additions & 1 deletion browser/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ source_set("ui") {
"webui/ai_chat/ai_chat_ui.h",
"webui/ai_chat/ai_chat_ui_page_handler.cc",
"webui/ai_chat/ai_chat_ui_page_handler.h",
"webui/ai_chat/ai_chat_untrusted_conversation_ui.cc",
"webui/ai_chat/ai_chat_untrusted_conversation_ui.h",
"webui/brave_adblock_internals_ui.cc",
"webui/brave_adblock_internals_ui.h",
"webui/brave_adblock_ui.cc",
Expand Down Expand Up @@ -772,8 +774,8 @@ source_set("ui") {
"//brave/components/ai_chat/core/browser",
"//brave/components/ai_chat/core/common",
"//brave/components/ai_chat/core/common/mojom",
"//brave/components/ai_chat/resources",
"//brave/components/ai_chat/resources/custom_site_distiller_scripts:generated_resources",
"//brave/components/ai_chat/resources/page:generated_resources",
"//brave/components/ai_rewriter/common/buildflags",
"//brave/components/brave_adaptive_captcha",
"//brave/components/brave_adblock_ui:generated_resources",
Expand Down
2 changes: 1 addition & 1 deletion browser/ui/brave_pages.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void ShowFullpageChat(Browser* browser) {
if (!ai_chat::features::IsAIChatHistoryEnabled()) {
return;
}
ShowSingletonTabOverwritingNTP(browser, GURL(kChatUIURL));
ShowSingletonTabOverwritingNTP(browser, GURL(kAIChatUIURL));
}

void ShowWebcompatReporter(Browser* browser) {
Expand Down
5 changes: 2 additions & 3 deletions browser/ui/views/side_panel/brave_side_panel_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
* 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 "base/strings/strcat.h"
#include "brave/browser/ai_chat/ai_chat_urls.h"
#include "brave/browser/ui/webui/ai_chat/ai_chat_ui.h"
#include "brave/components/ai_chat/core/browser/utils.h"
#include "brave/components/constants/webui_url_constants.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/views/side_panel/side_panel_registry.h"
#include "chrome/browser/ui/views/side_panel/side_panel_web_ui_view.h"
Expand All @@ -29,7 +28,7 @@ std::unique_ptr<views::View> CreateAIChatSidePanelWebView(
auto web_view = std::make_unique<SidePanelWebUIViewT<AIChatUI>>(
scope, base::RepeatingClosure(), base::RepeatingClosure(),
std::make_unique<WebUIContentsWrapperT<AIChatUI>>(
GURL(base::StrCat({kChatUIURL, "tab"})), profile.get(),
ai_chat::TabAssociatedConversationUrl(), profile.get(),
IDS_SIDEBAR_CHAT_SUMMARIZER_ITEM_TITLE,
/*esc_closes_ui=*/false));
web_view->ShowUI();
Expand Down
Loading

0 comments on commit 2fc11a2

Please sign in to comment.