Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(781)

Side by Side Diff: ios/chrome/browser/ui/omnibox/location_bar_view_ios.mm

Issue 2796793003: [ios] Adds a LocationBarController interface. (Closed)
Patch Set: Review. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import <UIKit/UIKit.h>
6
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "base/strings/string16.h"
11 #include "components/omnibox/browser/omnibox_edit_model.h"
12 #include "components/security_state/core/security_state_ui.h"
13 #include "components/strings/grit/components_strings.h"
14 #include "components/toolbar/toolbar_model.h"
15 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
16 #include "ios/chrome/browser/chrome_url_constants.h"
17 #include "ios/chrome/browser/experimental_flags.h"
18 #include "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
19 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
20 #include "ios/chrome/browser/ui/omnibox/location_bar_view_ios.h"
21 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
22 #include "ios/chrome/browser/ui/omnibox/omnibox_view_ios.h"
23 #include "ios/chrome/browser/ui/ui_util.h"
24 #import "ios/chrome/browser/ui/uikit_ui_util.h"
25 #include "ios/chrome/grit/ios_strings.h"
26 #include "ios/chrome/grit/ios_theme_resources.h"
27 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoF ontLoader.h"
28 #include "ios/web/public/navigation_item.h"
29 #include "ios/web/public/navigation_manager.h"
30 #include "ios/web/public/ssl_status.h"
31 #include "ios/web/public/web_state/web_state.h"
32 #include "ui/base/l10n/l10n_util.h"
33
34 #if !defined(__has_feature) || !__has_feature(objc_arc)
35 #error "This file requires ARC support."
36 #endif
37
38 namespace {
39 const CGFloat kClearTextButtonWidth = 28;
40 const CGFloat kClearTextButtonHeight = 28;
41
42 // Workaround for https://crbug.com/527084 . If there is connection
43 // information, always show the icon. Remove this once connection info
44 // is available via other UI: https://crbug.com/533581
45 bool DoesCurrentPageHaveCertInfo(web::WebState* webState) {
46 if (!webState)
47 return false;
48 web::NavigationManager* navigationMangager = webState->GetNavigationManager();
49 if (!navigationMangager)
50 return false;
51 web::NavigationItem* visibleItem = navigationMangager->GetVisibleItem();
52 if (!visibleItem)
53 return false;
54
55 const web::SSLStatus& SSLStatus = visibleItem->GetSSL();
56 // Evaluation of |security_style| SSLStatus field in WKWebView based app is an
57 // asynchronous operation, so for a short period of time SSLStatus may have
58 // non-null certificate and SECURITY_STYLE_UNKNOWN |security_style|.
59 return SSLStatus.certificate &&
60 SSLStatus.security_style != web::SECURITY_STYLE_UNKNOWN;
61 }
62
63 // Returns whether the |webState| is presenting an offline page.
64 bool IsCurrentPageOffline(web::WebState* webState) {
65 if (!webState)
66 return false;
67 auto* navigationManager = webState->GetNavigationManager();
68 auto* visibleItem = navigationManager->GetVisibleItem();
69 if (!visibleItem)
70 return false;
71 const GURL& url = visibleItem->GetURL();
72 return url.SchemeIs(kChromeUIScheme) && url.host() == kChromeUIOfflineHost;
73 }
74
75 } // namespace
76
77 // An ObjC bridge class to allow taps on the clear button to be sent to a C++
78 // class.
79 @interface OmniboxClearButtonBridge : NSObject
80
81 - (instancetype)initWithOmniboxView:(OmniboxViewIOS*)omniboxView
82 NS_DESIGNATED_INITIALIZER;
83
84 - (instancetype)init NS_UNAVAILABLE;
85
86 - (void)clearText;
87
88 @end
89
90 @implementation OmniboxClearButtonBridge {
91 OmniboxViewIOS* _omniboxView;
92 }
93
94 - (instancetype)initWithOmniboxView:(OmniboxViewIOS*)omniboxView {
95 self = [super init];
96 if (self) {
97 _omniboxView = omniboxView;
98 }
99 return self;
100 }
101
102 - (instancetype)init {
103 NOTREACHED();
104 return nil;
105 }
106
107 - (void)clearText {
108 _omniboxView->ClearText();
109 }
110
111 @end
112
113 LocationBarViewIOS::LocationBarViewIOS(OmniboxTextFieldIOS* field,
114 ios::ChromeBrowserState* browser_state,
115 id<PreloadProvider> preloader,
116 id<OmniboxPopupPositioner> positioner,
117 id<LocationBarDelegate> delegate)
118 : edit_view_(new OmniboxViewIOS(field,
119 this,
120 browser_state,
121 preloader,
122 positioner)),
123 field_(field),
124 delegate_(delegate) {
125 DCHECK([delegate_ toolbarModel]);
126 show_hint_text_ = true;
127
128 InstallLocationIcon();
129 CreateClearTextIcon(browser_state->IsOffTheRecord());
130 }
131
132 LocationBarViewIOS::~LocationBarViewIOS() {}
133
134 void LocationBarViewIOS::HideKeyboardAndEndEditing() {
135 edit_view_->HideKeyboardAndEndEditing();
136 }
137
138 void LocationBarViewIOS::SetShouldShowHintText(bool show_hint_text) {
139 show_hint_text_ = show_hint_text;
140 }
141
142 const OmniboxView* LocationBarViewIOS::GetLocationEntry() const {
143 return edit_view_.get();
144 }
145
146 OmniboxView* LocationBarViewIOS::GetLocationEntry() {
147 return edit_view_.get();
148 }
149
150 void LocationBarViewIOS::OnToolbarUpdated() {
151 edit_view_->UpdateAppearance();
152 OnChanged();
153 }
154
155 void LocationBarViewIOS::OnAutocompleteAccept(
156 const GURL& gurl,
157 WindowOpenDisposition disposition,
158 ui::PageTransition transition,
159 AutocompleteMatchType::Type type) {
160 if (gurl.is_valid()) {
161 transition = ui::PageTransitionFromInt(
162 transition | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
163 [delegate_ loadGURLFromLocationBar:gurl transition:transition];
164 }
165 }
166
167 void LocationBarViewIOS::OnChanged() {
168 const bool page_is_offline = IsCurrentPageOffline(GetWebState());
169 const int resource_id = edit_view_->GetIcon(page_is_offline);
170 [field_ setPlaceholderImage:resource_id];
171
172 // TODO(rohitrao): Can we get focus information from somewhere other than the
173 // model?
174 if (!IsIPadIdiom() && !edit_view_->model()->has_focus()) {
175 ToolbarModel* toolbarModel = [delegate_ toolbarModel];
176 if (toolbarModel) {
177 bool show_icon_for_state = security_state::ShouldAlwaysShowIcon(
178 toolbarModel->GetSecurityLevel(false));
179 bool page_has_downgraded_HTTPS =
180 experimental_flags::IsPageIconForDowngradedHTTPSEnabled() &&
181 DoesCurrentPageHaveCertInfo(GetWebState());
182 if (show_icon_for_state || page_has_downgraded_HTTPS || page_is_offline) {
183 [field_ showPlaceholderImage];
184 is_showing_placeholder_while_collapsed_ = true;
185 } else {
186 [field_ hidePlaceholderImage];
187 is_showing_placeholder_while_collapsed_ = false;
188 }
189 }
190 }
191 UpdateRightDecorations();
192 [delegate_ locationBarChanged];
193
194 NSString* placeholderText =
195 show_hint_text_ ? l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT) : nil;
196 [field_ setPlaceholder:placeholderText];
197 }
198
199 bool LocationBarViewIOS::IsShowingPlaceholderWhileCollapsed() {
200 return is_showing_placeholder_while_collapsed_;
201 }
202
203 void LocationBarViewIOS::OnInputInProgress(bool in_progress) {
204 if ([delegate_ toolbarModel])
205 [delegate_ toolbarModel]->set_input_in_progress(in_progress);
206 if (in_progress)
207 [delegate_ locationBarBeganEdit];
208 }
209
210 void LocationBarViewIOS::OnKillFocus() {
211 // Hide the location icon on phone. A subsequent call to OnChanged() will
212 // bring the icon back if needed.
213 if (!IsIPadIdiom()) {
214 [field_ hidePlaceholderImage];
215 is_showing_placeholder_while_collapsed_ = false;
216 }
217
218 // Update the placeholder icon.
219 const int resource_id =
220 edit_view_->GetIcon(IsCurrentPageOffline(GetWebState()));
221 [field_ setPlaceholderImage:resource_id];
222
223 // Show the placeholder text on iPad.
224 if (IsIPadIdiom()) {
225 NSString* placeholderText = l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT);
226 [field_ setPlaceholder:placeholderText];
227 }
228
229 UpdateRightDecorations();
230 [delegate_ locationBarHasResignedFirstResponder];
231 }
232
233 void LocationBarViewIOS::OnSetFocus() {
234 // Show the location icon on phone.
235 if (!IsIPadIdiom())
236 [field_ showPlaceholderImage];
237
238 // Update the placeholder icon.
239 const int resource_id =
240 edit_view_->GetIcon(IsCurrentPageOffline(GetWebState()));
241 [field_ setPlaceholderImage:resource_id];
242
243 // Hide the placeholder text on iPad.
244 if (IsIPadIdiom()) {
245 [field_ setPlaceholder:nil];
246 }
247 UpdateRightDecorations();
248 [delegate_ locationBarHasBecomeFirstResponder];
249 }
250
251 const ToolbarModel* LocationBarViewIOS::GetToolbarModel() const {
252 return [delegate_ toolbarModel];
253 }
254
255 ToolbarModel* LocationBarViewIOS::GetToolbarModel() {
256 return [delegate_ toolbarModel];
257 }
258
259 web::WebState* LocationBarViewIOS::GetWebState() {
260 return [delegate_ getWebState];
261 }
262
263 void LocationBarViewIOS::InstallLocationIcon() {
264 // Set the placeholder for empty omnibox.
265 UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
266 UIImage* image = NativeImage(IDR_IOS_OMNIBOX_SEARCH);
267 [button setImage:image forState:UIControlStateNormal];
268 [button setFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
269 [button addTarget:nil
270 action:@selector(chromeExecuteCommand:)
271 forControlEvents:UIControlEventTouchUpInside];
272 [button setTag:IDC_SHOW_PAGE_INFO];
273 SetA11yLabelAndUiAutomationName(
274 button, IDS_IOS_PAGE_INFO_SECURITY_BUTTON_ACCESSIBILITY_LABEL,
275 @"Page Security Info");
276 [button setIsAccessibilityElement:YES];
277
278 // Set chip text options.
279 [button setTitleColor:[UIColor colorWithWhite:0.631 alpha:1]
280 forState:UIControlStateNormal];
281 [button titleLabel].font =
282 [[MDFRobotoFontLoader sharedInstance] regularFontOfSize:12];
283 [field_ setLeftView:button];
284
285 // The placeholder image is only shown when in edit mode on iPhone, and always
286 // shown on iPad.
287 if (IsIPadIdiom())
288 [field_ setLeftViewMode:UITextFieldViewModeAlways];
289 else
290 [field_ setLeftViewMode:UITextFieldViewModeNever];
291 }
292
293 void LocationBarViewIOS::CreateClearTextIcon(bool is_incognito) {
294 UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
295 UIImage* omniBoxClearImage = is_incognito
296 ? NativeImage(IDR_IOS_OMNIBOX_CLEAR_OTR)
297 : NativeImage(IDR_IOS_OMNIBOX_CLEAR);
298 UIImage* omniBoxClearPressedImage =
299 is_incognito ? NativeImage(IDR_IOS_OMNIBOX_CLEAR_OTR_PRESSED)
300 : NativeImage(IDR_IOS_OMNIBOX_CLEAR_PRESSED);
301 [button setImage:omniBoxClearImage forState:UIControlStateNormal];
302 [button setImage:omniBoxClearPressedImage forState:UIControlStateHighlighted];
303
304 CGRect frame = CGRectZero;
305 frame.size = CGSizeMake(kClearTextButtonWidth, kClearTextButtonHeight);
306 [button setFrame:frame];
307
308 clear_button_bridge_.reset(
309 [[OmniboxClearButtonBridge alloc] initWithOmniboxView:edit_view_.get()]);
310 [button addTarget:clear_button_bridge_
311 action:@selector(clearText)
312 forControlEvents:UIControlEventTouchUpInside];
313 clear_text_button_.reset(button);
314
315 SetA11yLabelAndUiAutomationName(clear_text_button_,
316 IDS_IOS_ACCNAME_CLEAR_TEXT, @"Clear Text");
317 }
318
319 void LocationBarViewIOS::UpdateRightDecorations() {
320 DCHECK(clear_text_button_);
321 if (!edit_view_->model()->has_focus()) {
322 // Do nothing for iPhone. The right view will be set to nil after the
323 // omnibox animation is completed.
324 if (IsIPadIdiom())
325 [field_ setRightView:nil];
326 } else if ([field_ displayedText].empty() &&
327 ![field_ isShowingQueryRefinementChip]) {
328 [field_ setRightView:nil];
329 } else {
330 [field_ setRightView:clear_text_button_];
331 [clear_text_button_ setAlpha:1];
332 }
333 }
OLDNEW
« no previous file with comments | « ios/chrome/browser/ui/omnibox/location_bar_view_ios.h ('k') | ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698