Skip to content

Commit

Permalink
Added search promotion button in omnibox
Browse files Browse the repository at this point in the history
  • Loading branch information
simonhong committed Sep 13, 2024
1 parent 91d59fa commit 218f4a3
Show file tree
Hide file tree
Showing 22 changed files with 976 additions and 4 deletions.
7 changes: 7 additions & 0 deletions app/brave_generated_resources.grd
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,13 @@ Or change later at <ph name="SETTINGS_EXTENIONS_LINK">$2<ex>brave://settings/ext
<message name="IDS_ACC_BRAVE_SEARCH_CONVERSION_DISMISS_BUTTON" desc="Announcement when the dismiss button is focused.">
Dismiss Brave search conversion, press Enter to remove this suggestion
</message>
<message name="IDS_BRAVE_SEARCH_CONVERSION_BUTTON_LABEL" desc="The text for the search conversion promotion button">
Switch to Brave Search
</message>
<message name="IDS_BRAVE_SEARCH_CONVERSION_BUTTON_TOOLTIP" desc="The text for the search conversion button tooltip">
Switch to Brave Search
</message>

<!-- web Discovery InfoBar -->
<message name="IDS_WEB_DISCOVERY_INFOBAR_MESSAGE" desc="The text for web discovery infobar message">
Help improve <ph name="SEARCH_NAME">$1<ex>Brave Search</ex></ph> by sending anonymous usage data. <ph name="MORE_INFO">$2<ex>More info</ex></ph>
Expand Down
1 change: 1 addition & 0 deletions app/theme/brave_theme_resources.grd
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
<structure type="chrome_scaled_image" name="IDR_BRAVE_SEARCH_CONVERSION_BANNER_GRAPHIC_DARK" file="brave/brave_search_conversion_banner_graphic_dark.png" />
<structure type="chrome_scaled_image" name="IDR_BRAVE_SEARCH_CONVERSION_BANNER_GRAPHIC_DDG" file="brave/brave_search_conversion_banner_graphic_ddg.png" />
<structure type="chrome_scaled_image" name="IDR_BRAVE_SEARCH_CONVERSION_BANNER_GRAPHIC_DDG_DARK" file="brave/brave_search_conversion_banner_graphic_ddg_dark.png" />
<structure type="chrome_scaled_image" name="IDR_BRAVE_SEARCH_CONVERSION_BUTTON_BRAVE_SEARCH_ICON" file="brave/brave_search_conversion_button_brave_search_icon.png" />
<structure type="chrome_scaled_image" name="IDR_BRAVE_SEARCH_LOGO_IN_SEARCH_PROMOTION" file="brave/brave_search_logo_in_search_promotion.png" />
</if>
</structures>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions browser/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,10 @@ source_set("ui") {
"views/frame/vertical_tab_strip_widget_delegate_view.h",
"views/location_bar/brave_location_bar_view.cc",
"views/location_bar/brave_location_bar_view.h",
"views/location_bar/brave_search_conversion/promotion_button_controller.cc",
"views/location_bar/brave_search_conversion/promotion_button_controller.h",
"views/location_bar/brave_search_conversion/promotion_button_view.cc",
"views/location_bar/brave_search_conversion/promotion_button_view.h",
"views/location_bar/brave_star_view.cc",
"views/location_bar/brave_star_view.h",
"views/profiles/brave_avatar_toolbar_button.cc",
Expand Down
11 changes: 10 additions & 1 deletion browser/ui/color/brave_color_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@
E_CPONLY(kColorSearchConversionBannerTypeBackgroundBorderHovered) \
E_CPONLY(kColorSearchConversionBannerTypeBackgroundGradientFrom) \
E_CPONLY(kColorSearchConversionBannerTypeBackgroundGradientTo) \
E_CPONLY(kColorSearchConversionBannerTypeDescText)
E_CPONLY(kColorSearchConversionBannerTypeDescText) \
E_CPONLY(kColorSearchConversionButtonBorder) \
E_CPONLY(kColorSearchConversionButtonBackground) \
E_CPONLY(kColorSearchConversionButtonBackgroundHovered) \
E_CPONLY(kColorSearchConversionButtonText) \
E_CPONLY(kColorSearchConversionButtonCaratRight) \
E_CPONLY(kColorSearchConversionButtonCloseButton) \
E_CPONLY(kColorSearchConversionButtonCloseButtonHovered) \
E_CPONLY(kColorSearchConversionButtonShadow1) \
E_CPONLY(kColorSearchConversionButtonShadow2)

#define BRAVE_SIDEBAR_COLOR_IDS \
E_CPONLY(kColorSidebarAddBubbleBackground) \
Expand Down
20 changes: 20 additions & 0 deletions browser/ui/color/brave_color_mixer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,26 @@ void AddBraveColorMixerForAllThemes(ui::ColorProvider* provider,
// color by their color mixers.
mixer[kColorToolbarButtonActivated] = {SkColorSetRGB(0x7C, 0x91, 0xFF)};
mixer[kColorSidebarButtonPressed] = {kColorToolbarButtonActivated};

// Search conversion button in omnibox.
mixer[kColorSearchConversionButtonText] = {nala::kColorPrimary60};
mixer[kColorSearchConversionButtonBorder] = {nala::kColorPrimary20};
mixer[kColorSearchConversionButtonBackground] = {nala::kColorPrimary10};
mixer[kColorSearchConversionButtonBackgroundHovered] = {
nala::kColorPrimary20};
mixer[kColorSearchConversionButtonText] = {nala::kColorPrimary60};
mixer[kColorSearchConversionButtonCloseButton] = {
ui::AlphaBlend({nala::kColorIconInteractive},
{kColorSearchConversionButtonBackground}, 0.5 * 0xff)};
mixer[kColorSearchConversionButtonCloseButtonHovered] = {
ui::AlphaBlend({nala::kColorIconInteractive},
{kColorSearchConversionButtonBackground}, 0.7 * 0xff)};
mixer[kColorSearchConversionButtonCaratRight] = {
kColorSearchConversionButtonCloseButton};
mixer[kColorSearchConversionButtonShadow1] = {
SkColorSetA(SK_ColorBLACK, 0.05 * 255)};
mixer[kColorSearchConversionButtonShadow2] = {
SkColorSetA(SK_ColorBLACK, 0.1 * 255)};
}

} // namespace
Expand Down
24 changes: 24 additions & 0 deletions browser/ui/views/location_bar/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 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/.

source_set("browser_tests") {
testonly = true
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]

sources = [ "//brave/browser/ui/views/location_bar/brave_location_bar_view_browsertest.cc" ]

deps = [
"//base",
"//brave/components/brave_search_conversion",
"//chrome/browser",
"//chrome/browser/search_engines",
"//chrome/browser/ui",
"//chrome/common",
"//chrome/test",
"//chrome/test:test_support",
"//components/prefs",
"//ui/base:test_support",
]
}
19 changes: 19 additions & 0 deletions browser/ui/views/location_bar/brave_location_bar_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "brave/browser/ui/tabs/features.h"
#include "brave/browser/ui/views/brave_actions/brave_actions_container.h"
#include "brave/browser/ui/views/brave_news/brave_news_action_icon_view.h"
#include "brave/browser/ui/views/location_bar/brave_search_conversion/promotion_button_controller.h"
#include "brave/browser/ui/views/location_bar/brave_search_conversion/promotion_button_view.h"
#include "brave/browser/ui/views/playlist/playlist_action_icon_view.h"
#include "brave/browser/ui/views/toolbar/brave_toolbar_view.h"
#include "brave/components/commander/common/buildflags/buildflags.h"
Expand Down Expand Up @@ -125,6 +127,12 @@ void BraveLocationBarView::Init() {
AddChildView(std::make_unique<OnionLocationView>(browser_->profile()));
#endif

if (PromotionButtonController::PromotionEnabled(profile()->GetPrefs())) {
promotion_button_ = AddChildView(std::make_unique<PromotionButtonView>());
promotion_controller_ = std::make_unique<PromotionButtonController>(
promotion_button_, omnibox_view_, browser());
}

// brave action buttons
brave_actions_ = AddChildView(
std::make_unique<BraveActionsContainer>(browser_, profile()));
Expand Down Expand Up @@ -206,6 +214,13 @@ void BraveLocationBarView::OnChanged() {
brave_news_action_icon_view_->Update();
}

if (promotion_controller_) {
const bool show_button =
promotion_controller_->ShouldShowSearchPromotionButton() &&
!ShouldChipOverrideLocationIcon() && !ShouldShowKeywordBubble();
promotion_controller_->Show(show_button);
}

// OnChanged calls Layout
LocationBarView::OnChanged();
}
Expand Down Expand Up @@ -234,6 +249,10 @@ std::vector<views::View*> BraveLocationBarView::GetLeftMostTrailingViews() {
return views;
}

views::View* BraveLocationBarView::GetSearchPromotionButton() const {
return promotion_button_;
}

void BraveLocationBarView::RefreshBackground() {
LocationBarView::RefreshBackground();

Expand Down
7 changes: 7 additions & 0 deletions browser/ui/views/location_bar/brave_location_bar_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

class BraveActionsContainer;
class BraveActionsContainerTest;
class PromotionButtonController;
class PromotionButtonView;
class PlaylistActionIconView;
class RewardsBrowserTest;
class SkPath;
Expand Down Expand Up @@ -70,6 +72,7 @@ class BraveLocationBarView : public LocationBarView {
std::vector<views::View*> GetRightMostTrailingViews() override;
// Views that locates at left side of upstream's trailing views.
std::vector<views::View*> GetLeftMostTrailingViews() override;
views::View* GetSearchPromotionButton() const override;
void RefreshBackground() override;
void OnOmniboxBlurred() override;

Expand Down Expand Up @@ -104,6 +107,8 @@ class BraveLocationBarView : public LocationBarView {
playlist::PlaylistBrowserTestWithSitesUsingMediaSource,
MediaShouldBeExtractedFromBackground_DynamicallyAddedMedia);
FRIEND_TEST_ALL_PREFIXES(policy::BraveRewardsPolicyTest, RewardsIconIsHidden);
FRIEND_TEST_ALL_PREFIXES(BraveLocationBarViewBrowserTest,
SearchConversionButtonTest);
friend class ::BraveActionsContainerTest;
friend class ::RewardsBrowserTest;

Expand All @@ -113,6 +118,8 @@ class BraveLocationBarView : public LocationBarView {
std::unique_ptr<ViewShadow> shadow_;
raw_ptr<BraveActionsContainer> brave_actions_ = nullptr;
raw_ptr<BraveNewsActionIconView> brave_news_action_icon_view_ = nullptr;
std::unique_ptr<PromotionButtonController> promotion_controller_;
raw_ptr<PromotionButtonView> promotion_button_ = nullptr;
#if BUILDFLAG(ENABLE_TOR)
raw_ptr<OnionLocationView> onion_location_view_ = nullptr;
#endif
Expand Down
194 changes: 194 additions & 0 deletions browser/ui/views/location_bar/brave_location_bar_view_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/* 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/ui/views/location_bar/brave_location_bar_view.h"

#include <memory>

#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "brave/browser/ui/views/location_bar/brave_search_conversion/promotion_button_controller.h"
#include "brave/browser/ui/views/location_bar/brave_search_conversion/promotion_button_view.h"
#include "brave/components/brave_search_conversion/features.h"
#include "brave/components/brave_search_conversion/pref_names.h"
#include "brave/components/search_engines/brave_prepopulated_engines.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/search_test_utils.h"
#include "components/omnibox/browser/omnibox_edit_model.h"
#include "components/omnibox/browser/omnibox_view.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_data_util.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace {

testing::AssertionResult VerifyTemplateURLServiceLoad(
TemplateURLService* service) {
if (service->loaded()) {
return testing::AssertionSuccess();
}
search_test_utils::WaitForTemplateURLServiceToLoad(service);
if (service->loaded()) {
return testing::AssertionSuccess();
}
return testing::AssertionFailure() << "TemplateURLService isn't loaded";
}

} // namespace

class BraveLocationBarViewBrowserTest : public InProcessBrowserTest {
public:
BraveLocationBarViewBrowserTest() {
// Disabled by default.
EXPECT_FALSE(base::FeatureList::IsEnabled(
brave_search_conversion::features::kOmniboxPromotionButton));

features_.InitAndEnableFeature(
brave_search_conversion::features::kOmniboxPromotionButton);
}

BraveLocationBarView* location_bar() {
auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
return static_cast<BraveLocationBarView*>(
browser_view->toolbar()->location_bar());
}

OmniboxViewViews* omnibox_view() { return location_bar()->omnibox_view(); }

views::View* promotion_button_view() {
return location_bar()->GetSearchPromotionButton();
}

TemplateURLService* GetTemplateURLService() {
return TemplateURLServiceFactory::GetForProfile(browser()->profile());
}

content::WebContents* web_contents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}

void WaitUntil(base::RepeatingCallback<bool()> condition) {
if (condition.Run()) {
return;
}

base::RepeatingTimer scheduler;
scheduler.Start(FROM_HERE, base::Milliseconds(100),
base::BindLambdaForTesting([this, &condition]() {
if (condition.Run()) {
run_loop_->Quit();
}
}));
Run();
}

void Run() {
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
}

base::test::ScopedFeatureList features_;
std::unique_ptr<base::RunLoop> run_loop_;
};

IN_PROC_BROWSER_TEST_F(BraveLocationBarViewBrowserTest,
SearchConversionButtonTest) {
EXPECT_TRUE(VerifyTemplateURLServiceLoad(GetTemplateURLService()));

auto bing_search_data = TemplateURLDataFromPrepopulatedEngine(
TemplateURLPrepopulateData::brave_bing);
TemplateURL bing_template_url(*bing_search_data);

auto brave_search_data = TemplateURLDataFromPrepopulatedEngine(
TemplateURLPrepopulateData::brave_search);
TemplateURL brave_template_url(*brave_search_data);

// Set non brave search as a default provider and type any input.
// Check promotion button is launched.
GetTemplateURLService()->SetUserSelectedDefaultSearchProvider(
&bing_template_url);
location_bar()->FocusLocation(true);
omnibox_view()->SetUserText(u"a");
WaitUntil(base::BindLambdaForTesting(
[&]() { return omnibox_view()->model()->PopupIsOpen(); }));
EXPECT_TRUE(promotion_button_view()->GetVisible());

// Unfocus from the omnibox.
// Omnibox popup is hidden and promotion button will be gone also.
web_contents()->Focus();
WaitUntil(base::BindLambdaForTesting(
[&]() { return !omnibox_view()->model()->PopupIsOpen(); }));
EXPECT_FALSE(promotion_button_view()->GetVisible());

// Set brave search as a default provider and type any input.
GetTemplateURLService()->SetUserSelectedDefaultSearchProvider(
&brave_template_url);

// Check button is not shown with brave search.
location_bar()->FocusLocation(true);
omnibox_view()->SetUserText(u"a");
WaitUntil(base::BindLambdaForTesting(
[&]() { return omnibox_view()->model()->PopupIsOpen(); }));
EXPECT_FALSE(promotion_button_view()->GetVisible());

location_bar()->Revert();
WaitUntil(base::BindLambdaForTesting(
[&]() { return !omnibox_view()->model()->PopupIsOpen(); }));
EXPECT_FALSE(promotion_button_view()->GetVisible());

GetTemplateURLService()->SetUserSelectedDefaultSearchProvider(
&bing_template_url);

// Set dismissed and check button is not shown anymore.
browser()->profile()->GetPrefs()->SetBoolean(
brave_search_conversion::prefs::kDismissed, true);
omnibox_view()->SetUserText(u"a");
WaitUntil(base::BindLambdaForTesting(
[&]() { return omnibox_view()->model()->PopupIsOpen(); }));
EXPECT_FALSE(promotion_button_view()->GetVisible());

location_bar()->Revert();
WaitUntil(base::BindLambdaForTesting(
[&]() { return !omnibox_view()->model()->PopupIsOpen(); }));
EXPECT_FALSE(promotion_button_view()->GetVisible());

constexpr std::u16string search_term = u"a";

// Unset dismissed and simulate promotion button click.
browser()->profile()->GetPrefs()->SetBoolean(
brave_search_conversion::prefs::kDismissed, false);
location_bar()->FocusLocation(true);
omnibox_view()->SetUserText(search_term);
WaitUntil(base::BindLambdaForTesting(
[&]() { return omnibox_view()->model()->PopupIsOpen(); }));
EXPECT_TRUE(promotion_button_view()->GetVisible());

// Check brave search is set as default provider and brave search is loaded in
// active tab.
location_bar()
->promotion_controller_->SetDefaultAndLoadBraveSearchWithCurrentInput();
const TemplateURL* default_provider =
GetTemplateURLService()->GetDefaultSearchProvider();
const auto target_search_url = brave_template_url.GenerateSearchURL(
GetTemplateURLService()->search_terms_data(), search_term);
EXPECT_EQ(brave_template_url.prepopulate_id(),
default_provider->prepopulate_id());
content::WaitForLoadStop(web_contents());
EXPECT_EQ(target_search_url, web_contents()->GetVisibleURL());
}
Loading

0 comments on commit 218f4a3

Please sign in to comment.