// Copyright 2017 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/location_bar/ui_bundled/location_bar_coordinator.h"
#import "base/memory/ptr_util.h"
#import "base/metrics/histogram_functions.h"
#import "base/metrics/histogram_macros.h"
#import "base/strings/sys_string_conversions.h"
#import "components/feature_engagement/public/tracker.h"
#import "components/omnibox/browser/location_bar_model_impl.h"
#import "components/omnibox/browser/omnibox_edit_model.h"
#import "components/omnibox/browser/omnibox_view.h"
#import "components/open_from_clipboard/clipboard_recent_content.h"
#import "components/prefs/pref_service.h"
#import "components/profile_metrics/browser_profile_type.h"
#import "components/search_engines/util.h"
#import "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/autocomplete/model/autocomplete_scheme_classifier_impl.h"
#import "ios/chrome/browser/badges/ui_bundled/badge_button_factory.h"
#import "ios/chrome/browser/badges/ui_bundled/badge_delegate.h"
#import "ios/chrome/browser/badges/ui_bundled/badge_mediator.h"
#import "ios/chrome/browser/badges/ui_bundled/badge_view_controller.h"
#import "ios/chrome/browser/badges/ui_bundled/badge_view_visibility_delegate.h"
#import "ios/chrome/browser/browser_state_metrics/model/browser_state_metrics.h"
#import "ios/chrome/browser/contextual_panel/entrypoint/coordinator/contextual_panel_entrypoint_coordinator.h"
#import "ios/chrome/browser/contextual_panel/entrypoint/coordinator/contextual_panel_entrypoint_coordinator_delegate.h"
#import "ios/chrome/browser/contextual_panel/entrypoint/ui/contextual_panel_entrypoint_visibility_delegate.h"
#import "ios/chrome/browser/default_browser/model/default_browser_interest_signals.h"
#import "ios/chrome/browser/drag_and_drop/model/drag_item_util.h"
#import "ios/chrome/browser/drag_and_drop/model/url_drag_drop_handler.h"
#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
#import "ios/chrome/browser/infobars/model/infobar_metrics_recorder.h"
#import "ios/chrome/browser/lens_overlay/coordinator/lens_overlay_availability.h"
#import "ios/chrome/browser/location_bar/ui_bundled/location_bar_constants.h"
#import "ios/chrome/browser/location_bar/ui_bundled/location_bar_consumer.h"
#import "ios/chrome/browser/location_bar/ui_bundled/location_bar_mediator.h"
#import "ios/chrome/browser/location_bar/ui_bundled/location_bar_model_delegate_ios.h"
#import "ios/chrome/browser/location_bar/ui_bundled/location_bar_steady_view_consumer.h"
#import "ios/chrome/browser/location_bar/ui_bundled/location_bar_steady_view_mediator.h"
#import "ios/chrome/browser/location_bar/ui_bundled/location_bar_url_loader.h"
#import "ios/chrome/browser/location_bar/ui_bundled/location_bar_view_controller.h"
#import "ios/chrome/browser/ntp/model/new_tab_page_tab_helper.h"
#import "ios/chrome/browser/ntp/model/new_tab_page_util.h"
#import "ios/chrome/browser/overlays/model/public/overlay_presenter.h"
#import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
#import "ios/chrome/browser/shared/coordinator/layout_guide/layout_guide_util.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
#import "ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/commands/help_commands.h"
#import "ios/chrome/browser/shared/public/commands/lens_commands.h"
#import "ios/chrome/browser/shared/public/commands/load_query_commands.h"
#import "ios/chrome/browser/shared/public/commands/search_image_with_lens_command.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/shared/ui/util/pasteboard_util.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_updater.h"
#import "ios/chrome/browser/ui/lens/lens_entrypoint.h"
#import "ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_controller_delegate.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_coordinator.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_focus_delegate.h"
#import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.h"
#import "ios/chrome/browser/ui/omnibox/web_location_bar_impl.h"
#import "ios/chrome/browser/url_loading/model/image_search_param_generator.h"
#import "ios/chrome/browser/url_loading/model/url_loading_browser_agent.h"
#import "ios/chrome/browser/url_loading/model/url_loading_params.h"
#import "ios/chrome/browser/url_loading/model/url_loading_util.h"
#import "ios/chrome/browser/web/model/web_navigation_util.h"
#import "ios/public/provider/chrome/browser/lens/lens_api.h"
#import "ios/public/provider/chrome/browser/voice_search/voice_search_api.h"
#import "ios/web/public/navigation/navigation_manager.h"
#import "ios/web/public/navigation/referrer.h"
#import "ios/web/public/web_state.h"
#import "services/network/public/cpp/resource_request.h"
#import "ui/base/device_form_factor.h"
#import "url/gurl.h"
namespace {
const size_t kMaxURLDisplayChars = 32 * 1024;
} // namespace
@interface LocationBarCoordinator () <
ContextualPanelEntrypointCoordinatorDelegate,
LoadQueryCommands,
LocationBarViewControllerDelegate,
LocationBarConsumer,
LocationBarSteadyViewConsumer,
OmniboxControllerDelegate,
URLDragDataSource> {
// API endpoint for omnibox.
std::unique_ptr<WebLocationBarImpl> _locationBar;
// Observer that updates `viewController` for fullscreen events.
std::unique_ptr<FullscreenUIUpdater> _omniboxFullscreenUIUpdater;
// Observer that updates BadgeViewController for fullscreen events.
std::unique_ptr<FullscreenUIUpdater> _badgeFullscreenUIUpdater;
// Facade objects used by `_toolbarCoordinator`.
// Must outlive `_toolbarCoordinator`.
std::unique_ptr<LocationBarModelDelegateIOS> _locationBarModelDelegate;
std::unique_ptr<LocationBarModel> _locationBarModel;
}
// Whether the coordinator is started.
@property(nonatomic, assign, getter=isStarted) BOOL started;
// Mediator for the badges displayed in the LocationBar.
@property(nonatomic, strong) BadgeMediator* badgeMediator;
// ViewController for the badges displayed in the LocationBar.
@property(nonatomic, strong) BadgeViewController* badgeViewController;
// Coordinator for the contextual panel entrypoint.
@property(nonatomic, strong)
ContextualPanelEntrypointCoordinator* contextualPanelEntrypointCoordinator;
// Coordinator for the omnibox.
@property(nonatomic, strong) OmniboxCoordinator* omniboxCoordinator;
@property(nonatomic, strong) LocationBarMediator* mediator;
@property(nonatomic, strong) LocationBarSteadyViewMediator* steadyViewMediator;
@property(nonatomic, strong) LocationBarViewController* viewController;
@property(nonatomic, readonly) ChromeBrowserState* browserState;
@property(nonatomic, readonly) WebStateList* webStateList;
// Tracks calls in progress to -cancelOmniboxEdit to avoid calling it from
// itself when -resignFirstResponder causes -textFieldWillResignFirstResponder
// delegate call.
@property(nonatomic, assign) BOOL isCancellingOmniboxEdit;
// Handler for URL drag interactions.
@property(nonatomic, strong) URLDragDropHandler* dragDropHandler;
@end
@implementation LocationBarCoordinator
#pragma mark - Accessors
- (ChromeBrowserState*)browserState {
return self.browser ? self.browser->GetBrowserState() : nullptr;
}
- (WebStateList*)webStateList {
return self.browser ? self.browser->GetWebStateList() : nullptr;
}
#pragma mark - Public
- (UIViewController*)locationBarViewController {
return self.viewController;
}
- (instancetype)initWithBrowser:(Browser*)browser {
CHECK(browser);
return [super initWithBaseViewController:nil browser:browser];
}
- (void)start {
DCHECK(self.browser);
if (self.started)
return;
[self.browser->GetCommandDispatcher()
startDispatchingToTarget:self
forProtocol:@protocol(OmniboxCommands)];
[self.browser->GetCommandDispatcher()
startDispatchingToTarget:self
forProtocol:@protocol(LoadQueryCommands)];
BOOL isIncognito = self.browserState->IsOffTheRecord();
self.viewController = [[LocationBarViewController alloc] init];
self.viewController.incognito = isIncognito;
self.viewController.delegate = self;
// TODO(crbug.com/40670043): Use HandlerForProtocol after commands protocol
// clean up.
self.viewController.dispatcher =
static_cast<id<ActivityServiceCommands, ApplicationCommands,
LoadQueryCommands, OmniboxCommands>>(
self.browser->GetCommandDispatcher());
self.viewController.voiceSearchEnabled =
ios::provider::IsVoiceSearchEnabled();
self.viewController.layoutGuideCenter =
LayoutGuideCenterForBrowser(self.browser);
_locationBar = std::make_unique<WebLocationBarImpl>(self);
_locationBar->SetURLLoader(self);
_locationBarModelDelegate.reset(new LocationBarModelDelegateIOS(
self.browser->GetWebStateList(), self.browserState));
_locationBarModel = std::make_unique<LocationBarModelImpl>(
_locationBarModelDelegate.get(), kMaxURLDisplayChars);
self.omniboxCoordinator = [[OmniboxCoordinator alloc]
initWithBaseViewController:nil
browser:self.browser
omniboxClient:std::make_unique<ChromeOmniboxClientIOS>(
_locationBar.get(), self.browserState,
feature_engagement::TrackerFactory::
GetForBrowserState(
self.browserState))];
self.omniboxCoordinator.focusDelegate = self.delegate;
self.omniboxCoordinator.presenterDelegate = self.popupPresenterDelegate;
[self.omniboxCoordinator start];
[self.omniboxCoordinator.managedViewController
willMoveToParentViewController:self.viewController];
[self.viewController
addChildViewController:self.omniboxCoordinator.managedViewController];
[self.viewController setEditView:self.omniboxCoordinator.editView];
[self.omniboxCoordinator.managedViewController
didMoveToParentViewController:self.viewController];
self.viewController.offsetProvider = [self.omniboxCoordinator offsetProvider];
if (!isIncognito && IsContextualPanelEnabled()) {
self.contextualPanelEntrypointCoordinator =
[[ContextualPanelEntrypointCoordinator alloc]
initWithBaseViewController:self.viewController
browser:self.browser];
self.contextualPanelEntrypointCoordinator.delegate = self;
self.contextualPanelEntrypointCoordinator.visibilityDelegate =
self.viewController.contextualEntrypointVisibilityDelegate;
[self.contextualPanelEntrypointCoordinator start];
[self.viewController
addChildViewController:self.contextualPanelEntrypointCoordinator
.viewController];
[self.viewController
setContextualPanelEntrypointView:
self.contextualPanelEntrypointCoordinator.viewController.view];
[self.contextualPanelEntrypointCoordinator.viewController
didMoveToParentViewController:self.viewController];
}
if (!isIncognito && IsLensOverlayAvailable()) {
UIView* placeholderView = [[UIView alloc] init];
[self.viewController setPlaceholderView:placeholderView];
}
// Create button factory that wil be used by the ViewController to get
// BadgeButtons for a BadgeType.
BadgeButtonFactory* buttonFactory = [[BadgeButtonFactory alloc] init];
self.badgeViewController =
[[BadgeViewController alloc] initWithButtonFactory:buttonFactory];
self.badgeViewController.layoutGuideCenter =
LayoutGuideCenterForBrowser(self.browser);
self.badgeViewController.visibilityDelegate =
[self.viewController badgeViewVisibilityDelegate];
[self.viewController addChildViewController:self.badgeViewController];
[self.viewController setBadgeView:self.badgeViewController.view];
[self.badgeViewController didMoveToParentViewController:self.viewController];
// Create BadgeMediator and set the viewController as its consumer.
OverlayPresenter* overlayPresenter = OverlayPresenter::FromBrowser(
self.browser, OverlayModality::kInfobarBanner);
self.badgeMediator =
[[BadgeMediator alloc] initWithWebStateList:self.webStateList
overlayPresenter:overlayPresenter
isIncognito:isIncognito];
self.badgeMediator.consumer = self.badgeViewController;
// TODO(crbug.com/40670043): Use HandlerForProtocol after commands protocol
// clean up.
self.badgeMediator.dispatcher = static_cast<id<BrowserCoordinatorCommands>>(
self.browser->GetCommandDispatcher());
buttonFactory.delegate = self.badgeMediator;
FullscreenController* fullscreenController =
FullscreenController::FromBrowser(self.browser);
_badgeFullscreenUIUpdater = std::make_unique<FullscreenUIUpdater>(
fullscreenController, self.badgeViewController);
self.mediator = [[LocationBarMediator alloc] init];
self.mediator.templateURLService =
ios::TemplateURLServiceFactory::GetForBrowserState(self.browserState);
self.mediator.consumer = self;
self.mediator.webStateList = self.webStateList;
self.steadyViewMediator = [[LocationBarSteadyViewMediator alloc]
initWithLocationBarModel:[self locationBarModel]];
self.steadyViewMediator.webStateList = self.browser->GetWebStateList();
self.steadyViewMediator.webContentAreaOverlayPresenter =
OverlayPresenter::FromBrowser(self.browser,
OverlayModality::kWebContentArea);
self.steadyViewMediator.consumer = self;
_omniboxFullscreenUIUpdater = std::make_unique<FullscreenUIUpdater>(
fullscreenController, self.viewController);
self.started = YES;
[self setUpDragAndDrop];
}
- (void)stop {
if (!self.started)
return;
[self.browser->GetCommandDispatcher() stopDispatchingToTarget:self];
[self.contextualPanelEntrypointCoordinator stop];
self.contextualPanelEntrypointCoordinator.delegate = nil;
self.contextualPanelEntrypointCoordinator = nil;
// The popup has to be destroyed before the location bar.
[self.omniboxCoordinator stop];
[self.badgeMediator disconnect];
self.badgeMediator = nil;
_locationBar.reset();
self.viewController = nil;
[self.mediator disconnect];
self.mediator.templateURLService = nil;
self.mediator.consumer = nil;
self.mediator = nil;
[self.steadyViewMediator disconnect];
self.steadyViewMediator.webStateList = nullptr;
self.steadyViewMediator.webContentAreaOverlayPresenter = nil;
self.steadyViewMediator.consumer = nil;
self.steadyViewMediator = nil;
_locationBarModel = nullptr;
_locationBarModelDelegate = nullptr;
_badgeFullscreenUIUpdater = nullptr;
_omniboxFullscreenUIUpdater = nullptr;
self.started = NO;
}
- (BOOL)omniboxPopupHasAutocompleteResults {
return self.omniboxCoordinator.popupCoordinator.hasResults;
}
- (BOOL)showingOmniboxPopup {
return self.omniboxCoordinator.popupCoordinator.isOpen;
}
- (BOOL)isOmniboxFirstResponder {
return [self.omniboxCoordinator isOmniboxFirstResponder];
}
- (id<LocationBarAnimatee>)locationBarAnimatee {
return self.viewController;
}
- (id<EditViewAnimatee>)editViewAnimatee {
return self.omniboxCoordinator.animatee;
}
- (UIResponder<UITextInput>*)omniboxScribbleForwardingTarget {
return self.omniboxCoordinator.scribbleInput;
}
// Returns the toolbar omnibox consumer.
- (id<ToolbarOmniboxConsumer>)toolbarOmniboxConsumer {
return self.omniboxCoordinator.toolbarOmniboxConsumer;
}
#pragma mark - LoadQueryCommands
- (void)loadQuery:(NSString*)query immediately:(BOOL)immediately {
DCHECK(query);
// Since the query is not user typed, sanitize it to make sure it's safe.
std::u16string sanitizedQuery =
OmniboxView::SanitizeTextForPaste(base::SysNSStringToUTF16(query));
if (immediately) {
[self loadURLForQuery:sanitizedQuery];
} else {
[self focusOmnibox];
[self.omniboxCoordinator
insertTextToOmnibox:base::SysUTF16ToNSString(sanitizedQuery)];
}
}
#pragma mark - LocationBarURLLoader
- (void)loadGURLFromLocationBar:(const GURL&)url
postContent:
(TemplateURLRef::PostContent*)postContent
transition:(ui::PageTransition)transition
disposition:(WindowOpenDisposition)disposition
destination_url_entered_without_scheme:
(bool)destination_url_entered_without_scheme {
if (url.SchemeIs(url::kJavaScriptScheme)) {
LoadJavaScriptURL(url, self.browserState,
self.webStateList->GetActiveWebState());
} else {
// TODO(crbug.com/40550038): Is it ok to call `cancelOmniboxEdit` after
// `loadURL|? It doesn't seem to be causing major problems. If we call
// cancel before load, then any prerendered pages get destroyed before the
// call to load.
web::NavigationManager::WebLoadParams web_params =
web_navigation_util::CreateWebLoadParams(url, transition, postContent);
if (destination_url_entered_without_scheme) {
web_params.https_upgrade_type = web::HttpsUpgradeType::kOmnibox;
}
NSMutableDictionary<NSString*, NSString*>* combinedExtraHeaders =
[web_navigation_util::VariationHeadersForURL(
url, self.browserState->IsOffTheRecord()) mutableCopy];
[combinedExtraHeaders addEntriesFromDictionary:web_params.extra_headers];
web_params.extra_headers = [combinedExtraHeaders copy];
UrlLoadParams params = UrlLoadParams::InCurrentTab(web_params);
params.disposition = disposition;
UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params);
}
[self cancelOmniboxEdit];
}
#pragma mark - OmniboxCommands
- (void)focusOmniboxFromFakebox {
[self.omniboxCoordinator focusOmnibox];
}
- (void)focusOmnibox {
#if !defined(__IPHONE_16_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_16_0
// Dismiss the edit menu.
[[UIMenuController sharedMenuController] hideMenu];
#endif
// When the NTP and fakebox are visible, make the fakebox animates into place
// before focusing the omnibox.
if (IsVisibleURLNewTabPage([self webState]) &&
!self.browserState->IsOffTheRecord()) {
id<BrowserCoordinatorCommands> browserCoordinatorCommandsHandler =
HandlerForProtocol(self.browser->GetCommandDispatcher(),
BrowserCoordinatorCommands);
[browserCoordinatorCommandsHandler focusFakebox];
} else {
[self.omniboxCoordinator focusOmnibox];
}
}
- (void)cancelOmniboxEdit {
if (self.isCancellingOmniboxEdit) {
return;
}
self.isCancellingOmniboxEdit = YES;
[self.omniboxCoordinator endEditing];
self.isCancellingOmniboxEdit = NO;
}
#pragma mark - OmniboxControllerDelegate
- (web::WebState*)webState {
return self.webStateList->GetActiveWebState();
}
- (LocationBarModel*)locationBarModel {
return _locationBarModel.get();
}
#pragma mark - LocationBarViewControllerDelegate
- (void)locationBarSteadyViewTapped {
[self focusOmnibox];
}
- (void)locationBarCopyTapped {
StoreURLInPasteboard(self.webState->GetVisibleURL());
id<HelpCommands> helpHandler =
HandlerForProtocol(self.browser->GetCommandDispatcher(), HelpCommands);
[helpHandler presentInProductHelpWithType:InProductHelpType::kShareButton];
}
- (void)locationBarRequestScribbleTargetFocus {
[self.omniboxCoordinator focusOmniboxForScribble];
}
- (void)recordShareButtonPressed {
if (!self.browserState) {
return;
}
base::UmaHistogramEnumeration(
"iOS.LocationBar.ShareButton.PerProfileType",
profile_metrics::GetBrowserProfileType(self.browserState));
}
- (void)locationBarVisitCopyLinkTapped {
default_browser::NotifyOmniboxURLCopyPasteAndNavigate(
self.browserState->IsOffTheRecord(),
feature_engagement::TrackerFactory::GetForBrowserState(self.browserState),
self.browser->GetSceneState());
}
- (void)locationBarSearchCopiedTextTapped {
default_browser::NotifyOmniboxTextCopyPasteAndNavigate(
feature_engagement::TrackerFactory::GetForBrowserState(
self.browserState));
}
- (void)searchCopiedImage {
__weak LocationBarCoordinator* weakSelf = self;
ClipboardRecentContent::GetInstance()->GetRecentImageFromClipboard(
base::BindOnce(^(std::optional<gfx::Image> image) {
[weakSelf searchImage:std::move(image) usingLens:NO];
}));
}
- (void)lensCopiedImage {
__weak LocationBarCoordinator* weakSelf = self;
ClipboardRecentContent::GetInstance()->GetRecentImageFromClipboard(
base::BindOnce(^(std::optional<gfx::Image> image) {
[weakSelf searchImage:std::move(image) usingLens:YES];
}));
}
- (void)displayContextualPanelEntrypointView:(BOOL)display {
[self.contextualPanelEntrypointCoordinator.viewController
displayEntrypointView:display];
}
#pragma mark - ContextualPanelEntrypointCoordinatorDelegate
- (BOOL)canShowLargeContextualPanelEntrypoint:
(ContextualPanelEntrypointCoordinator*)coordinator {
return [self.viewController canShowLargeContextualPanelEntrypoint];
}
- (void)setLocationBarLabelCenteredBetweenContent:
(ContextualPanelEntrypointCoordinator*)coordinator
centered:(BOOL)centered {
[self.viewController setLocationBarLabelCenteredBetweenContent:centered];
}
#pragma mark - LocationBarConsumer
- (void)defocusOmnibox {
[self cancelOmniboxEdit];
}
- (void)updateSearchByImageSupported:(BOOL)searchByImageSupported {
self.viewController.searchByImageEnabled = searchByImageSupported;
}
- (void)updateLensImageSupported:(BOOL)lensImageSupported {
self.viewController.lensImageEnabled = lensImageSupported;
}
#pragma mark - LocationBarSteadyViewConsumer
- (void)updateLocationText:(NSString*)text clipTail:(BOOL)clipTail {
[self.omniboxCoordinator updateOmniboxState];
[self.viewController updateLocationText:text clipTail:clipTail];
[self.viewController updateForNTP:NO];
}
- (void)updateLocationIcon:(UIImage*)icon
securityStatusText:(NSString*)statusText {
[self.viewController updateLocationIcon:icon securityStatusText:statusText];
}
- (void)updateAfterNavigatingToNTP {
[self.viewController updateForNTP:YES];
}
- (void)updateLocationShareable:(BOOL)shareable {
[self.viewController setShareButtonEnabled:shareable];
}
#pragma mark - URLDragDataSource
- (URLInfo*)URLInfoForView:(UIView*)view {
// Disable drag and drop when the omnibox is focused, as it interferes with
// text interactions like moving the cursor (crbug.com/1502538).
if ([self isOmniboxFirstResponder]) {
return nil;
}
if (!self.webState->GetVisibleURL().is_valid()) {
return nil;
}
return [[URLInfo alloc]
initWithURL:self.webState->GetVisibleURL()
title:base::SysUTF16ToNSString(self.webState->GetTitle())];
}
- (UIBezierPath*)visiblePathForView:(UIView*)view {
return [UIBezierPath bezierPathWithRoundedRect:view.bounds
cornerRadius:view.bounds.size.height / 2];
}
#pragma mark - Private
// Navigate to `query` from omnibox.
- (void)loadURLForQuery:(const std::u16string&)query {
GURL searchURL;
metrics::OmniboxInputType type = AutocompleteInput::Parse(
query, std::string(), AutocompleteSchemeClassifierImpl(), nullptr,
nullptr, &searchURL);
if (type != metrics::OmniboxInputType::URL || !searchURL.is_valid()) {
searchURL = GetDefaultSearchURLForSearchTerms(
ios::TemplateURLServiceFactory::GetForBrowserState(self.browserState),
query);
}
if (searchURL.is_valid()) {
// It is necessary to include PAGE_TRANSITION_FROM_ADDRESS_BAR in the
// transition type is so that query-in-the-omnibox is triggered for the
// URL.
UrlLoadParams params = UrlLoadParams::InCurrentTab(searchURL);
params.web_params.transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params);
}
}
- (void)setUpDragAndDrop {
// iOS 15 adds Drag and Drop support to iPhones. This causes the long-press
// recognizer for showing the copy/paste menu to not appear until the user
// lifts their finger. The long-term solution is to move to the new
// UIContextMenu API, but for now, disable Drag from the omnibox on iOS 15
// iPhones.
// TODO (crbug.com/1247668): Reenable this after moving to new API and move
// this code back to -start.
if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_PHONE) {
return;
}
self.dragDropHandler = [[URLDragDropHandler alloc] init];
self.dragDropHandler.origin = WindowActivityLocationBarSteadyViewOrigin;
self.dragDropHandler.dragDataSource = self;
[self.viewController.view
addInteraction:[[UIDragInteraction alloc]
initWithDelegate:self.dragDropHandler]];
}
- (void)searchImage:(std::optional<gfx::Image>)optionalImage
usingLens:(BOOL)usingLens {
if (!optionalImage)
return;
// If the Browser has been destroyed, then the UI should
// no longer be active. Return early to avoid crashing.
Browser* browser = self.browser;
if (!browser)
return;
UIImage* image = optionalImage->ToUIImage();
if (usingLens) {
id<LensCommands> handler =
HandlerForProtocol(browser->GetCommandDispatcher(), LensCommands);
SearchImageWithLensCommand* command = [[SearchImageWithLensCommand alloc]
initWithImage:image
entryPoint:LensEntrypoint::OmniboxPostCapture];
[handler searchImageWithLens:command];
} else {
web::NavigationManager::WebLoadParams webParams =
ImageSearchParamGenerator::LoadParamsForImage(
image, ios::TemplateURLServiceFactory::GetForBrowserState(
browser->GetBrowserState()));
UrlLoadParams params = UrlLoadParams::InCurrentTab(webParams);
UrlLoadingBrowserAgent::FromBrowser(browser)->Load(params);
}
[self cancelOmniboxEdit];
}
@end