// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/lens_overlay/coordinator/lens_omnibox_client.h"
#import "base/feature_list.h"
#import "base/metrics/user_metrics.h"
#import "base/strings/string_util.h"
#import "base/strings/sys_string_conversions.h"
#import "base/strings/utf_string_conversions.h"
#import "base/task/thread_pool.h"
#import "components/favicon/ios/web_favicon_driver.h"
#import "components/feature_engagement/public/event_constants.h"
#import "components/feature_engagement/public/tracker.h"
#import "components/omnibox/browser/autocomplete_match.h"
#import "components/omnibox/browser/autocomplete_result.h"
#import "components/omnibox/browser/location_bar_model.h"
#import "components/omnibox/browser/omnibox_log.h"
#import "components/omnibox/browser/shortcuts_backend.h"
#import "components/omnibox/common/omnibox_features.h"
#import "components/search_engines/template_url_service.h"
#import "components/security_state/ios/security_state_utils.h"
#import "ios/chrome/browser/autocomplete/model/autocomplete_classifier_factory.h"
#import "ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.h"
#import "ios/chrome/browser/bookmarks/model/bookmark_model_factory.h"
#import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h"
#import "ios/chrome/browser/default_browser/model/default_browser_interest_signals.h"
#import "ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.h"
#import "ios/chrome/browser/lens_overlay/coordinator/lens_omnibox_client_delegate.h"
#import "ios/chrome/browser/lens_overlay/coordinator/lens_web_provider.h"
#import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
#import "ios/chrome/browser/sessions/model/ios_chrome_session_tab_helper.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/model/url/chrome_url_constants.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ios/web/public/navigation/navigation_context.h"
#import "ios/web/public/navigation/navigation_manager.h"
#import "ios/web/public/web_state.h"
#import "ui/base/l10n/l10n_util.h"
#import "ui/gfx/vector_icon_types.h"
#import "url/gurl.h"
LensOmniboxClient::LensOmniboxClient(
ChromeBrowserState* browser_state,
feature_engagement::Tracker* tracker,
id<LensWebProvider> web_provider,
id<LensOmniboxClientDelegate> omnibox_delegate)
: browser_state_(browser_state),
engagement_tracker_(tracker),
web_provider_(web_provider),
delegate_(omnibox_delegate) {
CHECK(engagement_tracker_);
}
LensOmniboxClient::~LensOmniboxClient() = default;
std::unique_ptr<AutocompleteProviderClient>
LensOmniboxClient::CreateAutocompleteProviderClient() {
return std::make_unique<AutocompleteProviderClientImpl>(browser_state_);
}
bool LensOmniboxClient::CurrentPageExists() const {
return web_provider_.webState != nullptr;
}
const GURL& LensOmniboxClient::GetURL() const {
if (web::WebState* web_state = web_provider_.webState) {
return web_state->GetVisibleURL();
}
return GURL::EmptyGURL();
}
bool LensOmniboxClient::IsLoading() const {
if (web::WebState* web_state = web_provider_.webState) {
return web_state->IsLoading();
}
return false;
}
bool LensOmniboxClient::IsPasteAndGoEnabled() const {
return false;
}
bool LensOmniboxClient::IsDefaultSearchProviderEnabled() const {
return true;
}
SessionID LensOmniboxClient::GetSessionID() const {
if (web::WebState* web_state = web_provider_.webState) {
return IOSChromeSessionTabHelper::FromWebState(web_state)->session_id();
}
return SessionID::InvalidValue();
}
PrefService* LensOmniboxClient::GetPrefs() {
return browser_state_->GetPrefs();
}
bookmarks::BookmarkModel* LensOmniboxClient::GetBookmarkModel() {
return ios::BookmarkModelFactory::GetForBrowserState(browser_state_);
}
AutocompleteControllerEmitter*
LensOmniboxClient::GetAutocompleteControllerEmitter() {
return nullptr;
}
TemplateURLService* LensOmniboxClient::GetTemplateURLService() {
return ios::TemplateURLServiceFactory::GetForBrowserState(browser_state_);
}
const AutocompleteSchemeClassifier& LensOmniboxClient::GetSchemeClassifier()
const {
return scheme_classifier_;
}
AutocompleteClassifier* LensOmniboxClient::GetAutocompleteClassifier() {
return ios::AutocompleteClassifierFactory::GetForBrowserState(browser_state_);
}
bool LensOmniboxClient::ShouldDefaultTypedNavigationsToHttps() const {
return base::FeatureList::IsEnabled(omnibox::kDefaultTypedNavigationsToHttps);
}
int LensOmniboxClient::GetHttpsPortForTesting() const {
return HttpsUpgradeServiceFactory::GetForBrowserState(browser_state_)
->GetHttpsPortForTesting();
}
bool LensOmniboxClient::IsUsingFakeHttpsForHttpsUpgradeTesting() const {
return HttpsUpgradeServiceFactory::GetForBrowserState(browser_state_)
->IsUsingFakeHttpsForTesting();
}
gfx::Image LensOmniboxClient::GetIconIfExtensionMatch(
const AutocompleteMatch& match) const {
// Extensions are not supported on iOS.
return gfx::Image();
}
std::u16string LensOmniboxClient::GetFormattedFullURL() const {
std::optional<TemplateURLService::SearchMetadata> metadata =
ios::TemplateURLServiceFactory::GetForBrowserState(browser_state_)
->ExtractSearchMetadata(GetURL());
if (metadata) {
return metadata->search_terms;
}
return u"";
}
std::u16string LensOmniboxClient::GetURLForDisplay() const {
return u"";
}
GURL LensOmniboxClient::GetNavigationEntryURL() const {
return GURL();
}
metrics::OmniboxEventProto::PageClassification
LensOmniboxClient::GetPageClassification(bool is_prefetch) {
return metrics::OmniboxEventProto::LENS_SIDE_PANEL_SEARCHBOX;
}
security_state::SecurityLevel LensOmniboxClient::GetSecurityLevel() const {
if (web::WebState* web_state = web_provider_.webState) {
return security_state::GetSecurityLevelForWebState(web_state);
}
return security_state::SecurityLevel::NONE;
}
net::CertStatus LensOmniboxClient::GetCertStatus() const {
return 0;
}
const gfx::VectorIcon& LensOmniboxClient::GetVectorIcon() const {
static const gfx::VectorIcon kEmptyVectorIcon = {};
return kEmptyVectorIcon;
}
bool LensOmniboxClient::ProcessExtensionKeyword(
const std::u16string& text,
const TemplateURL* template_url,
const AutocompleteMatch& match,
WindowOpenDisposition disposition) {
// Extensions are not supported on iOS.
return false;
}
void LensOmniboxClient::DiscardNonCommittedNavigations() {
web_provider_.webState->GetNavigationManager()->DiscardNonCommittedItems();
}
const std::u16string& LensOmniboxClient::GetTitle() const {
if (web::WebState* web_state = web_provider_.webState) {
return web_state->GetTitle();
}
return base::EmptyString16();
}
gfx::Image LensOmniboxClient::GetFavicon() const {
if (web::WebState* web_state = web_provider_.webState) {
favicon::WebFaviconDriver::FromWebState(web_state)->GetFavicon();
}
return gfx::Image();
}
void LensOmniboxClient::OnAutocompleteAccept(
const GURL& destination_url,
TemplateURLRef::PostContent* post_content,
WindowOpenDisposition disposition,
ui::PageTransition transition,
AutocompleteMatchType::Type match_type,
base::TimeTicks match_selection_timestamp,
bool destination_url_entered_without_scheme,
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) {
[delegate_ omniboxDidAcceptText:text destinationURL:destination_url];
}
base::WeakPtr<OmniboxClient> LensOmniboxClient::AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}