| Index: ios/chrome/browser/ui/omnibox/location_bar_view_ios.mm
|
| diff --git a/ios/chrome/browser/ui/omnibox/location_bar_view_ios.mm b/ios/chrome/browser/ui/omnibox/location_bar_view_ios.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e57613e9a452034335730ba3480044355e6dc7fc
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/omnibox/location_bar_view_ios.mm
|
| @@ -0,0 +1,336 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <UIKit/UIKit.h>
|
| +
|
| +#include "base/command_line.h"
|
| +#include "base/logging.h"
|
| +#include "base/macros.h"
|
| +#include "base/strings/string16.h"
|
| +#include "components/omnibox/browser/omnibox_edit_model.h"
|
| +#include "components/strings/grit/components_strings.h"
|
| +#include "components/toolbar/toolbar_model.h"
|
| +#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
|
| +#include "ios/chrome/browser/chrome_url_constants.h"
|
| +#include "ios/chrome/browser/experimental_flags.h"
|
| +#include "ios/chrome/browser/ui/commands/ios_command_ids.h"
|
| +#include "ios/chrome/browser/ui/omnibox/location_bar_view_ios.h"
|
| +#import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
|
| +#include "ios/chrome/browser/ui/omnibox/omnibox_view_ios.h"
|
| +#include "ios/chrome/browser/ui/ui_util.h"
|
| +#import "ios/chrome/browser/ui/uikit_ui_util.h"
|
| +#include "ios/chrome/grit/ios_strings.h"
|
| +#include "ios/chrome/grit/ios_theme_resources.h"
|
| +#import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h"
|
| +#include "ios/web/public/navigation_item.h"
|
| +#include "ios/web/public/navigation_manager.h"
|
| +#include "ios/web/public/ssl_status.h"
|
| +#include "ios/web/public/web_state/web_state.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "ui/base/resource/resource_bundle.h"
|
| +#include "ui/gfx/geometry/rect.h"
|
| +#include "ui/gfx/image/image.h"
|
| +
|
| +namespace {
|
| +const CGFloat kClearTextButtonWidth = 28;
|
| +const CGFloat kClearTextButtonHeight = 28;
|
| +
|
| +// Workaround for https://crbug.com/527084 . If there is connection
|
| +// information, always show the icon. Remove this once connection info
|
| +// is available via other UI: https://crbug.com/533581
|
| +bool DoesCurrentPageHaveCertInfo(web::WebState* webState) {
|
| + if (!webState)
|
| + return false;
|
| + web::NavigationManager* navigationMangager = webState->GetNavigationManager();
|
| + if (!navigationMangager)
|
| + return false;
|
| + web::NavigationItem* visibleItem = navigationMangager->GetVisibleItem();
|
| + if (!visibleItem)
|
| + return false;
|
| +
|
| + const web::SSLStatus& SSLStatus = visibleItem->GetSSL();
|
| + // Evaluation of |security_style| SSLStatus field in WKWebView based app is an
|
| + // asynchronous operation, so for a short period of time SSLStatus may have
|
| + // non-null certificate and SECURITY_STYLE_UNKNOWN |security_style|.
|
| + return SSLStatus.certificate &&
|
| + SSLStatus.security_style != web::SECURITY_STYLE_UNKNOWN;
|
| +}
|
| +
|
| +// Returns whether the |webState| is presenting an offline page.
|
| +bool IsCurrentPageOffline(web::WebState* webState) {
|
| + if (!webState)
|
| + return false;
|
| + auto navigationManager = webState->GetNavigationManager();
|
| + auto visibleItem = navigationManager->GetVisibleItem();
|
| + if (!visibleItem)
|
| + return false;
|
| + const GURL& url = visibleItem->GetURL();
|
| + return url.SchemeIs(kChromeUIScheme) && url.host() == kChromeUIOfflineHost;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// An ObjC bridge class to allow taps on the clear button to be sent to a C++
|
| +// class.
|
| +@interface OmniboxClearButtonBridge : NSObject
|
| +
|
| +- (instancetype)initWithOmniboxView:(OmniboxViewIOS*)omniboxView
|
| + NS_DESIGNATED_INITIALIZER;
|
| +
|
| +- (instancetype)init NS_UNAVAILABLE;
|
| +
|
| +- (void)clearText;
|
| +
|
| +@end
|
| +
|
| +@implementation OmniboxClearButtonBridge {
|
| + OmniboxViewIOS* _omniboxView;
|
| +}
|
| +
|
| +- (instancetype)initWithOmniboxView:(OmniboxViewIOS*)omniboxView {
|
| + self = [super init];
|
| + if (self) {
|
| + _omniboxView = omniboxView;
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (instancetype)init {
|
| + NOTREACHED();
|
| + return nil;
|
| +}
|
| +
|
| +- (void)clearText {
|
| + _omniboxView->ClearText();
|
| +}
|
| +
|
| +@end
|
| +
|
| +LocationBarViewIOS::LocationBarViewIOS(OmniboxTextFieldIOS* field,
|
| + ios::ChromeBrowserState* browser_state,
|
| + id<PreloadProvider> preloader,
|
| + id<OmniboxPopupPositioner> positioner,
|
| + id<LocationBarDelegate> delegate)
|
| + : edit_view_(new OmniboxViewIOS(field,
|
| + this,
|
| + browser_state,
|
| + preloader,
|
| + positioner)),
|
| + field_(field),
|
| + delegate_(delegate) {
|
| + DCHECK([delegate_ toolbarModel]);
|
| + show_hint_text_ = true;
|
| +
|
| + InstallLocationIcon();
|
| + CreateClearTextIcon(browser_state->IsOffTheRecord());
|
| +}
|
| +
|
| +LocationBarViewIOS::~LocationBarViewIOS() {}
|
| +
|
| +void LocationBarViewIOS::HideKeyboardAndEndEditing() {
|
| + edit_view_->HideKeyboardAndEndEditing();
|
| +}
|
| +
|
| +void LocationBarViewIOS::SetShouldShowHintText(bool show_hint_text) {
|
| + show_hint_text_ = show_hint_text;
|
| +}
|
| +
|
| +const OmniboxView* LocationBarViewIOS::GetLocationEntry() const {
|
| + return edit_view_.get();
|
| +}
|
| +
|
| +OmniboxView* LocationBarViewIOS::GetLocationEntry() {
|
| + return edit_view_.get();
|
| +}
|
| +
|
| +void LocationBarViewIOS::OnToolbarUpdated() {
|
| + edit_view_->UpdateAppearance();
|
| + OnChanged();
|
| +}
|
| +
|
| +void LocationBarViewIOS::OnAutocompleteAccept(
|
| + const GURL& gurl,
|
| + WindowOpenDisposition disposition,
|
| + ui::PageTransition transition,
|
| + AutocompleteMatchType::Type type) {
|
| + if (gurl.is_valid()) {
|
| + transition = ui::PageTransitionFromInt(
|
| + transition | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
|
| + [delegate_ loadGURLFromLocationBar:gurl transition:transition];
|
| + }
|
| +}
|
| +
|
| +void LocationBarViewIOS::OnChanged() {
|
| + const bool page_is_offline = IsCurrentPageOffline(GetWebState());
|
| + const int resource_id = edit_view_->GetIcon(page_is_offline);
|
| + [field_ setPlaceholderImage:resource_id];
|
| +
|
| + // TODO(rohitrao): Can we get focus information from somewhere other than the
|
| + // model?
|
| + if (!IsIPadIdiom() && !edit_view_->model()->has_focus()) {
|
| + ToolbarModel* toolbarModel = [delegate_ toolbarModel];
|
| + if (toolbarModel) {
|
| + bool page_is_secure =
|
| + toolbarModel->GetSecurityLevel(false) != security_state::NONE;
|
| + bool page_has_downgraded_HTTPS =
|
| + experimental_flags::IsPageIconForDowngradedHTTPSEnabled() &&
|
| + DoesCurrentPageHaveCertInfo(GetWebState());
|
| + if (page_is_secure || page_has_downgraded_HTTPS || page_is_offline) {
|
| + [field_ showPlaceholderImage];
|
| + is_showing_placeholder_while_collapsed_ = true;
|
| + } else {
|
| + [field_ hidePlaceholderImage];
|
| + is_showing_placeholder_while_collapsed_ = false;
|
| + }
|
| + }
|
| + }
|
| + UpdateRightDecorations();
|
| + [delegate_ locationBarChanged];
|
| +
|
| + NSString* placeholderText =
|
| + show_hint_text_ ? l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT) : nil;
|
| + [field_ setPlaceholder:placeholderText];
|
| +}
|
| +
|
| +bool LocationBarViewIOS::IsShowingPlaceholderWhileCollapsed() {
|
| + return is_showing_placeholder_while_collapsed_;
|
| +}
|
| +
|
| +void LocationBarViewIOS::OnInputInProgress(bool in_progress) {
|
| + if ([delegate_ toolbarModel])
|
| + [delegate_ toolbarModel]->set_input_in_progress(in_progress);
|
| + if (in_progress)
|
| + [delegate_ locationBarBeganEdit];
|
| +}
|
| +
|
| +void LocationBarViewIOS::OnKillFocus() {
|
| + // Hide the location icon on phone. A subsequent call to OnChanged() will
|
| + // bring the icon back if needed.
|
| + if (!IsIPadIdiom()) {
|
| + [field_ hidePlaceholderImage];
|
| + is_showing_placeholder_while_collapsed_ = false;
|
| + }
|
| +
|
| + // Update the placeholder icon.
|
| + const int resource_id =
|
| + edit_view_->GetIcon(IsCurrentPageOffline(GetWebState()));
|
| + [field_ setPlaceholderImage:resource_id];
|
| +
|
| + // Show the placeholder text on iPad.
|
| + if (IsIPadIdiom()) {
|
| + NSString* placeholderText = l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT);
|
| + [field_ setPlaceholder:placeholderText];
|
| + }
|
| +
|
| + UpdateRightDecorations();
|
| + [delegate_ locationBarHasResignedFirstResponder];
|
| +}
|
| +
|
| +void LocationBarViewIOS::OnSetFocus() {
|
| + // Show the location icon on phone.
|
| + if (!IsIPadIdiom())
|
| + [field_ showPlaceholderImage];
|
| +
|
| + // Update the placeholder icon.
|
| + const int resource_id =
|
| + edit_view_->GetIcon(IsCurrentPageOffline(GetWebState()));
|
| + [field_ setPlaceholderImage:resource_id];
|
| +
|
| + // Hide the placeholder text on iPad.
|
| + if (IsIPadIdiom()) {
|
| + [field_ setPlaceholder:nil];
|
| + }
|
| + UpdateRightDecorations();
|
| + [delegate_ locationBarHasBecomeFirstResponder];
|
| +}
|
| +
|
| +const ToolbarModel* LocationBarViewIOS::GetToolbarModel() const {
|
| + return [delegate_ toolbarModel];
|
| +}
|
| +
|
| +ToolbarModel* LocationBarViewIOS::GetToolbarModel() {
|
| + return [delegate_ toolbarModel];
|
| +}
|
| +
|
| +web::WebState* LocationBarViewIOS::GetWebState() {
|
| + return [delegate_ getWebState];
|
| +}
|
| +
|
| +void LocationBarViewIOS::InstallLocationIcon() {
|
| + // Set the placeholder for empty omnibox.
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + gfx::Image magImage = rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_SEARCH);
|
| + UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
|
| + UIImage* image = magImage.ToUIImage();
|
| + [button setImage:image forState:UIControlStateNormal];
|
| + [button setFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
|
| + [button addTarget:nil
|
| + action:@selector(chromeExecuteCommand:)
|
| + forControlEvents:UIControlEventTouchUpInside];
|
| + [button setTag:IDC_SHOW_PAGE_INFO];
|
| + SetA11yLabelAndUiAutomationName(
|
| + button, IDS_IOS_PAGE_INFO_SECURITY_BUTTON_ACCESSIBILITY_LABEL,
|
| + @"Page Security Info");
|
| + [button setIsAccessibilityElement:YES];
|
| +
|
| + // Set chip text options.
|
| + [button setTitleColor:[UIColor colorWithWhite:0.631 alpha:1]
|
| + forState:UIControlStateNormal];
|
| + [button titleLabel].font =
|
| + [[MDFRobotoFontLoader sharedInstance] regularFontOfSize:12];
|
| + [field_ setLeftView:button];
|
| +
|
| + // The placeholder image is only shown when in edit mode on iPhone, and always
|
| + // shown on iPad.
|
| + if (IsIPadIdiom())
|
| + [field_ setLeftViewMode:UITextFieldViewModeAlways];
|
| + else
|
| + [field_ setLeftViewMode:UITextFieldViewModeNever];
|
| +}
|
| +
|
| +void LocationBarViewIOS::CreateClearTextIcon(bool is_incognito) {
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
|
| + UIImage* omniBoxClearImage =
|
| + is_incognito
|
| + ? rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_CLEAR_OTR).ToUIImage()
|
| + : rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_CLEAR).ToUIImage();
|
| + UIImage* omniBoxClearPressedImage =
|
| + is_incognito
|
| + ? rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_CLEAR_OTR_PRESSED)
|
| + .ToUIImage()
|
| + : rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_CLEAR_PRESSED).ToUIImage();
|
| + [button setImage:omniBoxClearImage forState:UIControlStateNormal];
|
| + [button setImage:omniBoxClearPressedImage forState:UIControlStateHighlighted];
|
| +
|
| + CGRect frame = CGRectZero;
|
| + frame.size = CGSizeMake(kClearTextButtonWidth, kClearTextButtonHeight);
|
| + [button setFrame:frame];
|
| +
|
| + clear_button_bridge_.reset(
|
| + [[OmniboxClearButtonBridge alloc] initWithOmniboxView:edit_view_.get()]);
|
| + [button addTarget:clear_button_bridge_
|
| + action:@selector(clearText)
|
| + forControlEvents:UIControlEventTouchUpInside];
|
| + clear_text_button_.reset([button retain]);
|
| +
|
| + SetA11yLabelAndUiAutomationName(clear_text_button_,
|
| + IDS_IOS_ACCNAME_CLEAR_TEXT, @"Clear Text");
|
| +}
|
| +
|
| +void LocationBarViewIOS::UpdateRightDecorations() {
|
| + DCHECK(clear_text_button_);
|
| + if (!edit_view_->model()->has_focus()) {
|
| + // Do nothing for iPhone. The right view will be set to nil after the
|
| + // omnibox animation is completed.
|
| + if (IsIPadIdiom())
|
| + [field_ setRightView:nil];
|
| + } else if ([field_ displayedText].empty() &&
|
| + ![field_ isShowingQueryRefinementChip]) {
|
| + [field_ setRightView:nil];
|
| + } else {
|
| + [field_ setRightView:clear_text_button_];
|
| + [clear_text_button_ setAlpha:1];
|
| + }
|
| +}
|
|
|