blob: db15d86a25a6a84fc90fc969b3f36ac28fd8645c [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/omnibox/browser/contextual_search_provider.h"
#include <memory>
#include <ranges>
#include <string>
#include "base/memory/scoped_refptr.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/autocomplete_provider_listener.h"
#include "components/omnibox/browser/mock_autocomplete_provider_client.h"
#include "components/omnibox/browser/test_scheme_classifier.h"
#include "components/omnibox/common/omnibox_feature_configs.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
#include "third_party/metrics_proto/omnibox_focus_type.pb.h"
#include "url/gurl.h"
class ContextualSearchProviderTest : public testing::Test,
public AutocompleteProviderListener {
public:
ContextualSearchProviderTest() = default;
ContextualSearchProviderTest(const ContextualSearchProviderTest&) = delete;
ContextualSearchProviderTest& operator=(const ContextualSearchProviderTest&) =
delete;
void SetUp() override {
contextual_search_config_.Get().show_open_lens_action = true;
client_ = std::make_unique<MockAutocompleteProviderClient>();
provider_ = new ContextualSearchProvider(client_.get(), this);
}
protected:
// AutocompleteProviderListener:
void OnProviderUpdate(bool updated_matches,
const AutocompleteProvider* provider) override {}
omnibox_feature_configs::ScopedConfigForTesting<
omnibox_feature_configs::ContextualSearch>
contextual_search_config_;
std::unique_ptr<MockAutocompleteProviderClient> client_;
scoped_refptr<ContextualSearchProvider> provider_;
};
TEST_F(ContextualSearchProviderTest, LensAdActionConditions) {
auto has_actions = [this] {
return std::ranges::any_of(provider_->matches(), [](const auto& match) {
return !!match.takeover_action;
});
};
EXPECT_CALL(*client_, IsLensEnabled()).WillRepeatedly(testing::Return(true));
EXPECT_CALL(*client_, AreLensEntrypointsVisible())
.WillRepeatedly(testing::Return(true));
{
AutocompleteInput input(u"nonempty input text",
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("https://example.com"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_DEFAULT);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
EXPECT_FALSE(has_actions());
}
{
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("https://example.com"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
EXPECT_TRUE(has_actions());
}
{
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("chrome://flags"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
EXPECT_FALSE(has_actions());
}
{
// Include action for local files.
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("file:///home/me/personal/local/file.pdf"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
EXPECT_TRUE(has_actions());
}
{
// Exclude action from other local schemes.
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("chrome://flags"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
EXPECT_FALSE(has_actions());
}
{
// Lens action missing if Lens is disabled.
EXPECT_CALL(*client_, IsLensEnabled()).WillOnce(testing::Return(false));
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("https://example.com"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
EXPECT_FALSE(has_actions());
}
{
// When backspacing to empty input, action should not be shown.
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("https://example.com"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_DEFAULT);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
EXPECT_FALSE(has_actions());
}
}
TEST_F(ContextualSearchProviderTest, LensAdActionFillsEditAndElidesWwwOnly) {
EXPECT_CALL(*client_, IsLensEnabled()).WillRepeatedly(testing::Return(true));
EXPECT_CALL(*client_, AreLensEntrypointsVisible())
.WillRepeatedly(testing::Return(true));
{
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("https://something.example.com"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
const AutocompleteMatch& match = provider_->matches()[0];
EXPECT_FALSE(match.fill_into_edit.empty());
EXPECT_EQ(match.contents, u"something.example.com");
}
{
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("https://www.example.com"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
const AutocompleteMatch& match = provider_->matches()[0];
EXPECT_FALSE(match.fill_into_edit.empty());
EXPECT_EQ(match.contents, u"example.com");
}
{
AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL("file:///home/personal/file.pdf"));
input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done());
const AutocompleteMatch& match = provider_->matches()[0];
EXPECT_FALSE(match.fill_into_edit.empty());
EXPECT_EQ(match.contents, u"");
}
}