OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/browser/ui/ntp/google_landing_view_controller.h" | 5 #import "ios/chrome/browser/ui/ntp/google_landing_view_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/mac/foundation_util.h" | 9 #include "base/mac/foundation_util.h" |
10 #include "base/metrics/user_metrics.h" | 10 #include "base/metrics/user_metrics.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 #import "ios/chrome/browser/ui/url_loader.h" | 28 #import "ios/chrome/browser/ui/url_loader.h" |
29 #include "ios/chrome/common/string_util.h" | 29 #include "ios/chrome/common/string_util.h" |
30 #include "ios/chrome/grit/ios_strings.h" | 30 #include "ios/chrome/grit/ios_strings.h" |
31 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat
erialSnackbar.h" | 31 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat
erialSnackbar.h" |
32 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" | 32 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" |
33 #import "ios/web/public/web_state/context_menu_params.h" | 33 #import "ios/web/public/web_state/context_menu_params.h" |
34 #import "net/base/mac/url_conversions.h" | 34 #import "net/base/mac/url_conversions.h" |
35 #include "ui/base/l10n/l10n_util.h" | 35 #include "ui/base/l10n/l10n_util.h" |
36 #include "ui/base/page_transition_types.h" | 36 #include "ui/base/page_transition_types.h" |
37 | 37 |
| 38 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 39 #error "This file requires ARC support." |
| 40 #endif |
| 41 |
38 using base::UserMetricsAction; | 42 using base::UserMetricsAction; |
39 | 43 |
40 namespace { | 44 namespace { |
41 | 45 |
42 enum { | 46 enum { |
43 SectionWithOmnibox, | 47 SectionWithOmnibox, |
44 SectionWithMostVisited, | 48 SectionWithMostVisited, |
45 NumberOfCollectionViewSections, | 49 NumberOfCollectionViewSections, |
46 }; | 50 }; |
47 | 51 |
48 const UIEdgeInsets kSearchBoxStretchInsets = {3, 3, 3, 3}; | 52 const UIEdgeInsets kSearchBoxStretchInsets = {3, 3, 3, 3}; |
49 | 53 |
50 const CGFloat kHintLabelSidePadding = 12; | 54 const CGFloat kHintLabelSidePadding = 12; |
51 const CGFloat kWhatsNewHeaderHiddenHeight = 8; | 55 const CGFloat kWhatsNewHeaderHiddenHeight = 8; |
52 const NSInteger kMaxNumMostVisitedFaviconRows = 2; | 56 const NSInteger kMaxNumMostVisitedFaviconRows = 2; |
53 const CGFloat kShiftTilesDownAnimationDuration = 0.2; | 57 const CGFloat kShiftTilesDownAnimationDuration = 0.2; |
54 | 58 |
55 } // namespace | 59 } // namespace |
56 | 60 |
57 @interface GoogleLandingViewController ()<OverscrollActionsControllerDelegate, | 61 @interface GoogleLandingViewController ()<OverscrollActionsControllerDelegate, |
58 UICollectionViewDataSource, | 62 UICollectionViewDataSource, |
59 UICollectionViewDelegate, | 63 UICollectionViewDelegate, |
60 UICollectionViewDelegateFlowLayout, | 64 UICollectionViewDelegateFlowLayout, |
61 UIGestureRecognizerDelegate, | 65 UIGestureRecognizerDelegate, |
62 WhatsNewHeaderViewDelegate> { | 66 WhatsNewHeaderViewDelegate> { |
63 // Fake omnibox. | 67 // Fake omnibox. |
64 base::scoped_nsobject<UIButton> _searchTapTarget; | 68 UIButton* _searchTapTarget; |
65 | 69 |
66 // A collection view for the most visited sites. | 70 // A collection view for the most visited sites. |
67 base::scoped_nsobject<UICollectionView> _mostVisitedView; | 71 UICollectionView* _mostVisitedView; |
68 | 72 |
69 // The overscroll actions controller managing accelerators over the toolbar. | 73 // The overscroll actions controller managing accelerators over the toolbar. |
70 base::scoped_nsobject<OverscrollActionsController> | 74 OverscrollActionsController* _overscrollActionsController; |
71 _overscrollActionsController; | |
72 | 75 |
73 // |YES| when notifications indicate the omnibox is focused. | 76 // |YES| when notifications indicate the omnibox is focused. |
74 BOOL _omniboxFocused; | 77 BOOL _omniboxFocused; |
75 | 78 |
76 // Tap and swipe gesture recognizers when the omnibox is focused. | 79 // Tap and swipe gesture recognizers when the omnibox is focused. |
77 base::scoped_nsobject<UITapGestureRecognizer> _tapGestureRecognizer; | 80 UITapGestureRecognizer* _tapGestureRecognizer; |
78 base::scoped_nsobject<UISwipeGestureRecognizer> _swipeGestureRecognizer; | 81 UISwipeGestureRecognizer* _swipeGestureRecognizer; |
79 | 82 |
80 // Handles displaying the context menu for all form factors. | 83 // Handles displaying the context menu for all form factors. |
81 base::scoped_nsobject<ContextMenuCoordinator> _contextMenuCoordinator; | 84 ContextMenuCoordinator* _contextMenuCoordinator; |
82 | 85 |
83 // URL of the last deleted most viewed entry. If present the UI to restore it | 86 // URL of the last deleted most viewed entry. If present the UI to restore it |
84 // is shown. | 87 // is shown. |
85 base::scoped_nsobject<NSURL> _deletedUrl; | 88 NSURL* _deletedUrl; |
86 | 89 |
87 // |YES| if the view has finished its first layout. This is useful when | 90 // |YES| if the view has finished its first layout. This is useful when |
88 // determining if the view has sized itself for tablet. | 91 // determining if the view has sized itself for tablet. |
89 BOOL _viewLoaded; | 92 BOOL _viewLoaded; |
90 | 93 |
91 // |YES| if the fakebox header should be animated on scroll. | 94 // |YES| if the fakebox header should be animated on scroll. |
92 BOOL _animateHeader; | 95 BOOL _animateHeader; |
93 | 96 |
94 // |YES| if the collection scrollView is scrolled all the way to the top. Used | 97 // |YES| if the collection scrollView is scrolled all the way to the top. Used |
95 // to lock this position in place on various frame changes. | 98 // to lock this position in place on various frame changes. |
96 BOOL _scrolledToTop; | 99 BOOL _scrolledToTop; |
97 | 100 |
98 // |YES| if this NTP panel is visible. When set to |NO| various UI updates | 101 // |YES| if this NTP panel is visible. When set to |NO| various UI updates |
99 // are ignored. | 102 // are ignored. |
100 BOOL _isShowing; | 103 BOOL _isShowing; |
101 | 104 |
102 CFTimeInterval _shiftTilesDownStartTime; | 105 CFTimeInterval _shiftTilesDownStartTime; |
103 CGSize _mostVisitedCellSize; | 106 CGSize _mostVisitedCellSize; |
104 base::scoped_nsobject<NSLayoutConstraint> _hintLabelLeadingConstraint; | 107 NSLayoutConstraint* _hintLabelLeadingConstraint; |
105 base::scoped_nsobject<NSLayoutConstraint> _voiceTapTrailingConstraint; | 108 NSLayoutConstraint* _voiceTapTrailingConstraint; |
106 base::scoped_nsobject<NSLayoutConstraint> _doodleHeightConstraint; | 109 NSLayoutConstraint* _doodleHeightConstraint; |
107 base::scoped_nsobject<NSLayoutConstraint> _doodleTopMarginConstraint; | 110 NSLayoutConstraint* _doodleTopMarginConstraint; |
108 base::scoped_nsobject<NSLayoutConstraint> _searchFieldWidthConstraint; | 111 NSLayoutConstraint* _searchFieldWidthConstraint; |
109 base::scoped_nsobject<NSLayoutConstraint> _searchFieldHeightConstraint; | 112 NSLayoutConstraint* _searchFieldHeightConstraint; |
110 base::scoped_nsobject<NSLayoutConstraint> _searchFieldTopMarginConstraint; | 113 NSLayoutConstraint* _searchFieldTopMarginConstraint; |
111 base::scoped_nsobject<NewTabPageHeaderView> _headerView; | 114 NewTabPageHeaderView* _headerView; |
112 base::scoped_nsobject<WhatsNewHeaderView> _promoHeaderView; | 115 WhatsNewHeaderView* _promoHeaderView; |
113 base::WeakNSProtocol<id<GoogleLandingDataSource>> _dataSource; | 116 __weak id<GoogleLandingDataSource> _dataSource; |
114 base::WeakNSProtocol<id<UrlLoader, OmniboxFocuser>> _dispatcher; | 117 __weak id<UrlLoader, OmniboxFocuser> _dispatcher; |
115 } | 118 } |
116 | 119 |
117 // Whether the Google logo or doodle is being shown. | 120 // Whether the Google logo or doodle is being shown. |
118 @property(nonatomic, assign) BOOL logoIsShowing; | 121 @property(nonatomic, assign) BOOL logoIsShowing; |
119 | 122 |
120 // Exposes view and methods to drive the doodle. | 123 // Exposes view and methods to drive the doodle. |
121 @property(nonatomic, assign) id<LogoVendor> logoVendor; | 124 @property(nonatomic, weak) id<LogoVendor> logoVendor; |
122 | 125 |
123 // |YES| if this consumer is has voice search enabled. | 126 // |YES| if this consumer is has voice search enabled. |
124 @property(nonatomic, assign) BOOL voiceSearchIsEnabled; | 127 @property(nonatomic, assign) BOOL voiceSearchIsEnabled; |
125 | 128 |
126 // Gets the maximum number of sites shown. | 129 // Gets the maximum number of sites shown. |
127 @property(nonatomic, assign) NSUInteger maximumMostVisitedSitesShown; | 130 @property(nonatomic, assign) NSUInteger maximumMostVisitedSitesShown; |
128 | 131 |
129 // Gets the text of a what's new promo. | 132 // Gets the text of a what's new promo. |
130 @property(nonatomic, retain) NSString* promoText; | 133 @property(nonatomic, strong) NSString* promoText; |
131 | 134 |
132 // Gets the icon of a what's new promo. | 135 // Gets the icon of a what's new promo. |
133 // TODO(crbug.com/694750): This should not be WhatsNewIcon. | 136 // TODO(crbug.com/694750): This should not be WhatsNewIcon. |
134 @property(nonatomic, assign) WhatsNewIcon promoIcon; | 137 @property(nonatomic, assign) WhatsNewIcon promoIcon; |
135 | 138 |
136 // |YES| if a what's new promo can be displayed. | 139 // |YES| if a what's new promo can be displayed. |
137 @property(nonatomic, assign) BOOL promoCanShow; | 140 @property(nonatomic, assign) BOOL promoCanShow; |
138 | 141 |
139 // The number of tabs to show in the google landing fake toolbar. | 142 // The number of tabs to show in the google landing fake toolbar. |
140 @property(nonatomic, assign) int tabCount; | 143 @property(nonatomic, assign) int tabCount; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 UIViewAutoresizingFlexibleWidth]; | 224 UIViewAutoresizingFlexibleWidth]; |
222 | 225 |
223 // Initialise |shiftTilesDownStartTime| to a sentinel value to indicate that | 226 // Initialise |shiftTilesDownStartTime| to a sentinel value to indicate that |
224 // the animation has not yet started. | 227 // the animation has not yet started. |
225 _shiftTilesDownStartTime = -1; | 228 _shiftTilesDownStartTime = -1; |
226 _mostVisitedCellSize = [self mostVisitedCellSize]; | 229 _mostVisitedCellSize = [self mostVisitedCellSize]; |
227 _isShowing = YES; | 230 _isShowing = YES; |
228 _scrolledToTop = NO; | 231 _scrolledToTop = NO; |
229 _animateHeader = YES; | 232 _animateHeader = YES; |
230 | 233 |
231 _tapGestureRecognizer.reset([[UITapGestureRecognizer alloc] | 234 _tapGestureRecognizer = |
232 initWithTarget:self | 235 [[UITapGestureRecognizer alloc] initWithTarget:self |
233 action:@selector(blurOmnibox)]); | 236 action:@selector(blurOmnibox)]; |
234 [_tapGestureRecognizer setDelegate:self]; | 237 [_tapGestureRecognizer setDelegate:self]; |
235 _swipeGestureRecognizer.reset([[UISwipeGestureRecognizer alloc] | 238 _swipeGestureRecognizer = |
236 initWithTarget:self | 239 [[UISwipeGestureRecognizer alloc] initWithTarget:self |
237 action:@selector(blurOmnibox)]); | 240 action:@selector(blurOmnibox)]; |
238 [_swipeGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionDown]; | 241 [_swipeGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionDown]; |
239 | 242 |
240 self.leftMargin = | 243 self.leftMargin = |
241 content_suggestions::centeredTilesMarginForWidth([self viewWidth]); | 244 content_suggestions::centeredTilesMarginForWidth([self viewWidth]); |
242 | 245 |
243 [self addSearchField]; | 246 [self addSearchField]; |
244 [self addMostVisited]; | 247 [self addMostVisited]; |
245 [self addOverscrollActions]; | 248 [self addOverscrollActions]; |
246 [self reload]; | 249 [self reload]; |
247 _viewLoaded = YES; | 250 _viewLoaded = YES; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 // Invalidate layout to handle the cases where the layout is changed when the | 299 // Invalidate layout to handle the cases where the layout is changed when the |
297 // NTP is not presented (e.g. tab backgrounded). | 300 // NTP is not presented (e.g. tab backgrounded). |
298 [[_mostVisitedView collectionViewLayout] invalidateLayout]; | 301 [[_mostVisitedView collectionViewLayout] invalidateLayout]; |
299 } | 302 } |
300 | 303 |
301 - (void)dealloc { | 304 - (void)dealloc { |
302 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 305 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
303 [_mostVisitedView setDelegate:nil]; | 306 [_mostVisitedView setDelegate:nil]; |
304 [_mostVisitedView setDataSource:nil]; | 307 [_mostVisitedView setDataSource:nil]; |
305 [_overscrollActionsController invalidate]; | 308 [_overscrollActionsController invalidate]; |
306 [super dealloc]; | |
307 } | 309 } |
308 | 310 |
309 #pragma mark - Properties | 311 #pragma mark - Properties |
310 | 312 |
311 - (id<GoogleLandingDataSource>)dataSource { | 313 - (id<GoogleLandingDataSource>)dataSource { |
312 return _dataSource; | 314 return _dataSource; |
313 } | 315 } |
314 | 316 |
315 - (void)setDataSource:(id<GoogleLandingDataSource>)dataSource { | 317 - (void)setDataSource:(id<GoogleLandingDataSource>)dataSource { |
316 _dataSource.reset(dataSource); | 318 _dataSource = dataSource; |
317 } | 319 } |
318 | 320 |
319 - (id<UrlLoader, OmniboxFocuser>)dispatcher { | 321 - (id<UrlLoader, OmniboxFocuser>)dispatcher { |
320 return _dispatcher; | 322 return _dispatcher; |
321 } | 323 } |
322 | 324 |
323 - (void)setDispatcher:(id<UrlLoader, OmniboxFocuser>)dispatcher { | 325 - (void)setDispatcher:(id<UrlLoader, OmniboxFocuser>)dispatcher { |
324 _dispatcher.reset(dispatcher); | 326 _dispatcher = dispatcher; |
325 } | 327 } |
326 | 328 |
327 #pragma mark - Private | 329 #pragma mark - Private |
328 | 330 |
329 - (CGSize)mostVisitedCellSize { | 331 - (CGSize)mostVisitedCellSize { |
330 if (IsIPadIdiom()) { | 332 if (IsIPadIdiom()) { |
331 // On iPads, split-screen and slide-over may require showing smaller cells. | 333 // On iPads, split-screen and slide-over may require showing smaller cells. |
332 CGSize maximumCellSize = [MostVisitedCell maximumSize]; | 334 CGSize maximumCellSize = [MostVisitedCell maximumSize]; |
333 CGSize viewSize = self.view.bounds.size; | 335 CGSize viewSize = self.view.bounds.size; |
334 CGFloat smallestDimension = | 336 CGFloat smallestDimension = |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 whatsNewFrame.origin.y = omniboxHeaderHeight; | 394 whatsNewFrame.origin.y = omniboxHeaderHeight; |
393 [_promoHeaderView setFrame:whatsNewFrame]; | 395 [_promoHeaderView setFrame:whatsNewFrame]; |
394 } | 396 } |
395 if (IsIPadIdiom()) | 397 if (IsIPadIdiom()) |
396 [_searchTapTarget setHidden:!self.logoIsShowing]; | 398 [_searchTapTarget setHidden:!self.logoIsShowing]; |
397 } | 399 } |
398 } | 400 } |
399 | 401 |
400 // Initialize and add a search field tap target and a voice search button. | 402 // Initialize and add a search field tap target and a voice search button. |
401 - (void)addSearchField { | 403 - (void)addSearchField { |
402 _searchTapTarget.reset([[UIButton alloc] init]); | 404 _searchTapTarget = [[UIButton alloc] init]; |
403 if (IsIPadIdiom()) { | 405 if (IsIPadIdiom()) { |
404 UIImage* searchBoxImage = [[UIImage imageNamed:@"ntp_google_search_box"] | 406 UIImage* searchBoxImage = [[UIImage imageNamed:@"ntp_google_search_box"] |
405 resizableImageWithCapInsets:kSearchBoxStretchInsets]; | 407 resizableImageWithCapInsets:kSearchBoxStretchInsets]; |
406 [_searchTapTarget setBackgroundImage:searchBoxImage | 408 [_searchTapTarget setBackgroundImage:searchBoxImage |
407 forState:UIControlStateNormal]; | 409 forState:UIControlStateNormal]; |
408 } | 410 } |
409 [_searchTapTarget setAdjustsImageWhenHighlighted:NO]; | 411 [_searchTapTarget setAdjustsImageWhenHighlighted:NO]; |
410 [_searchTapTarget addTarget:self | 412 [_searchTapTarget addTarget:self |
411 action:@selector(searchFieldTapped:) | 413 action:@selector(searchFieldTapped:) |
412 forControlEvents:UIControlEventTouchUpInside]; | 414 forControlEvents:UIControlEventTouchUpInside]; |
413 [_searchTapTarget | 415 [_searchTapTarget |
414 setAccessibilityLabel:l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT)]; | 416 setAccessibilityLabel:l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT)]; |
415 // Set isAccessibilityElement to NO so that Voice Search button is accessible. | 417 // Set isAccessibilityElement to NO so that Voice Search button is accessible. |
416 [_searchTapTarget setIsAccessibilityElement:NO]; | 418 [_searchTapTarget setIsAccessibilityElement:NO]; |
417 | 419 |
418 // Set up fakebox hint label. | 420 // Set up fakebox hint label. |
419 UILabel* searchHintLabel = [[[UILabel alloc] init] autorelease]; | 421 UILabel* searchHintLabel = [[UILabel alloc] init]; |
420 content_suggestions::configureSearchHintLabel(searchHintLabel, | 422 content_suggestions::configureSearchHintLabel(searchHintLabel, |
421 _searchTapTarget.get()); | 423 _searchTapTarget); |
422 | 424 |
423 _hintLabelLeadingConstraint.reset([[searchHintLabel.leadingAnchor | 425 _hintLabelLeadingConstraint = [searchHintLabel.leadingAnchor |
424 constraintEqualToAnchor:[_searchTapTarget leadingAnchor] | 426 constraintEqualToAnchor:[_searchTapTarget leadingAnchor] |
425 constant:kHintLabelSidePadding] retain]); | 427 constant:kHintLabelSidePadding]; |
426 [_hintLabelLeadingConstraint setActive:YES]; | 428 [_hintLabelLeadingConstraint setActive:YES]; |
427 | 429 |
428 // Add a voice search button. | 430 // Add a voice search button. |
429 UIButton* voiceTapTarget = [[[UIButton alloc] init] autorelease]; | 431 UIButton* voiceTapTarget = [[UIButton alloc] init]; |
430 content_suggestions::configureVoiceSearchButton(voiceTapTarget, | 432 content_suggestions::configureVoiceSearchButton(voiceTapTarget, |
431 _searchTapTarget.get()); | 433 _searchTapTarget); |
432 | 434 |
433 _voiceTapTrailingConstraint.reset([[voiceTapTarget.trailingAnchor | 435 _voiceTapTrailingConstraint = [voiceTapTarget.trailingAnchor |
434 constraintEqualToAnchor:[_searchTapTarget trailingAnchor]] retain]); | 436 constraintEqualToAnchor:[_searchTapTarget trailingAnchor]]; |
435 [NSLayoutConstraint activateConstraints:@[ | 437 [NSLayoutConstraint activateConstraints:@[ |
436 [searchHintLabel.trailingAnchor | 438 [searchHintLabel.trailingAnchor |
437 constraintEqualToAnchor:voiceTapTarget.leadingAnchor], | 439 constraintEqualToAnchor:voiceTapTarget.leadingAnchor], |
438 _voiceTapTrailingConstraint | 440 _voiceTapTrailingConstraint |
439 ]]; | 441 ]]; |
440 | 442 |
441 if (self.voiceSearchIsEnabled) { | 443 if (self.voiceSearchIsEnabled) { |
442 [voiceTapTarget addTarget:self | 444 [voiceTapTarget addTarget:self |
443 action:@selector(loadVoiceSearch:) | 445 action:@selector(loadVoiceSearch:) |
444 forControlEvents:UIControlEventTouchUpInside]; | 446 forControlEvents:UIControlEventTouchUpInside]; |
(...skipping 12 matching lines...) Expand all Loading... |
457 } | 459 } |
458 | 460 |
459 - (void)preloadVoiceSearch:(id)sender { | 461 - (void)preloadVoiceSearch:(id)sender { |
460 DCHECK(self.voiceSearchIsEnabled); | 462 DCHECK(self.voiceSearchIsEnabled); |
461 [sender removeTarget:self | 463 [sender removeTarget:self |
462 action:@selector(preloadVoiceSearch:) | 464 action:@selector(preloadVoiceSearch:) |
463 forControlEvents:UIControlEventTouchDown]; | 465 forControlEvents:UIControlEventTouchDown]; |
464 | 466 |
465 // Use a GenericChromeCommand because |sender| already has a tag set for a | 467 // Use a GenericChromeCommand because |sender| already has a tag set for a |
466 // different command. | 468 // different command. |
467 base::scoped_nsobject<GenericChromeCommand> command( | 469 GenericChromeCommand* command = |
468 [[GenericChromeCommand alloc] initWithTag:IDC_PRELOAD_VOICE_SEARCH]); | 470 [[GenericChromeCommand alloc] initWithTag:IDC_PRELOAD_VOICE_SEARCH]; |
469 [sender chromeExecuteCommand:command]; | 471 [sender chromeExecuteCommand:command]; |
470 } | 472 } |
471 | 473 |
472 // Initialize and add a panel with most visited sites. | 474 // Initialize and add a panel with most visited sites. |
473 - (void)addMostVisited { | 475 - (void)addMostVisited { |
474 CGRect mostVisitedFrame = [self.view bounds]; | 476 CGRect mostVisitedFrame = [self.view bounds]; |
475 base::scoped_nsobject<UICollectionViewFlowLayout> flowLayout; | 477 UICollectionViewFlowLayout* flowLayout; |
476 if (IsIPadIdiom()) | 478 if (IsIPadIdiom()) |
477 flowLayout.reset([[UICollectionViewFlowLayout alloc] init]); | 479 flowLayout = [[UICollectionViewFlowLayout alloc] init]; |
478 else | 480 else |
479 flowLayout.reset([[MostVisitedLayout alloc] init]); | 481 flowLayout = [[MostVisitedLayout alloc] init]; |
480 | 482 |
481 [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical]; | 483 [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical]; |
482 [flowLayout setItemSize:_mostVisitedCellSize]; | 484 [flowLayout setItemSize:_mostVisitedCellSize]; |
483 [flowLayout setMinimumInteritemSpacing:8]; | 485 [flowLayout setMinimumInteritemSpacing:8]; |
484 [flowLayout setMinimumLineSpacing:content_suggestions::spacingBetweenTiles()]; | 486 [flowLayout setMinimumLineSpacing:content_suggestions::spacingBetweenTiles()]; |
485 DCHECK(!_mostVisitedView); | 487 DCHECK(!_mostVisitedView); |
486 _mostVisitedView.reset([[UICollectionView alloc] | 488 _mostVisitedView = [[UICollectionView alloc] initWithFrame:mostVisitedFrame |
487 initWithFrame:mostVisitedFrame | 489 collectionViewLayout:flowLayout]; |
488 collectionViewLayout:flowLayout]); | |
489 [_mostVisitedView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | | 490 [_mostVisitedView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | |
490 UIViewAutoresizingFlexibleWidth]; | 491 UIViewAutoresizingFlexibleWidth]; |
491 [_mostVisitedView setDelegate:self]; | 492 [_mostVisitedView setDelegate:self]; |
492 [_mostVisitedView setDataSource:self]; | 493 [_mostVisitedView setDataSource:self]; |
493 [_mostVisitedView registerClass:[MostVisitedCell class] | 494 [_mostVisitedView registerClass:[MostVisitedCell class] |
494 forCellWithReuseIdentifier:@"classCell"]; | 495 forCellWithReuseIdentifier:@"classCell"]; |
495 [_mostVisitedView setBackgroundColor:[UIColor clearColor]]; | 496 [_mostVisitedView setBackgroundColor:[UIColor clearColor]]; |
496 [_mostVisitedView setBounces:YES]; | 497 [_mostVisitedView setBounces:YES]; |
497 [_mostVisitedView setShowsHorizontalScrollIndicator:NO]; | 498 [_mostVisitedView setShowsHorizontalScrollIndicator:NO]; |
498 [_mostVisitedView setShowsVerticalScrollIndicator:NO]; | 499 [_mostVisitedView setShowsVerticalScrollIndicator:NO]; |
(...skipping 12 matching lines...) Expand all Loading... |
511 [_headerView updateSearchFieldWidth:_searchFieldWidthConstraint | 512 [_headerView updateSearchFieldWidth:_searchFieldWidthConstraint |
512 height:_searchFieldHeightConstraint | 513 height:_searchFieldHeightConstraint |
513 topMargin:_searchFieldTopMarginConstraint | 514 topMargin:_searchFieldTopMarginConstraint |
514 subviewConstraints:constraints | 515 subviewConstraints:constraints |
515 logoIsShowing:self.logoIsShowing | 516 logoIsShowing:self.logoIsShowing |
516 forOffset:[_mostVisitedView contentOffset].y]; | 517 forOffset:[_mostVisitedView contentOffset].y]; |
517 } | 518 } |
518 | 519 |
519 - (void)addOverscrollActions { | 520 - (void)addOverscrollActions { |
520 if (!IsIPadIdiom()) { | 521 if (!IsIPadIdiom()) { |
521 _overscrollActionsController.reset([[OverscrollActionsController alloc] | 522 _overscrollActionsController = [[OverscrollActionsController alloc] |
522 initWithScrollView:_mostVisitedView]); | 523 initWithScrollView:_mostVisitedView]; |
523 [_overscrollActionsController setStyle:OverscrollStyle::NTP_NON_INCOGNITO]; | 524 [_overscrollActionsController setStyle:OverscrollStyle::NTP_NON_INCOGNITO]; |
524 [_overscrollActionsController setDelegate:self]; | 525 [_overscrollActionsController setDelegate:self]; |
525 } | 526 } |
526 } | 527 } |
527 | 528 |
528 // Check to see if the promo label should be hidden. | 529 // Check to see if the promo label should be hidden. |
529 - (void)hideWhatsNewIfNecessary { | 530 - (void)hideWhatsNewIfNecessary { |
530 if (![_promoHeaderView isHidden] && !self.promoCanShow) { | 531 if (![_promoHeaderView isHidden] && !self.promoCanShow) { |
531 [_promoHeaderView setHidden:YES]; | 532 [_promoHeaderView setHidden:YES]; |
532 [self.view setNeedsLayout]; | 533 [self.view setNeedsLayout]; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 // -numberOfItems increases enough to add a new row and change the height | 666 // -numberOfItems increases enough to add a new row and change the height |
666 // of _mostVisitedView. | 667 // of _mostVisitedView. |
667 [_mostVisitedView reloadData]; | 668 [_mostVisitedView reloadData]; |
668 [[_mostVisitedView collectionViewLayout] invalidateLayout]; | 669 [[_mostVisitedView collectionViewLayout] invalidateLayout]; |
669 [self.view setNeedsLayout]; | 670 [self.view setNeedsLayout]; |
670 } | 671 } |
671 | 672 |
672 - (void)addConstraintsForLogoView:(UIView*)logoView | 673 - (void)addConstraintsForLogoView:(UIView*)logoView |
673 searchField:(UIView*)searchField | 674 searchField:(UIView*)searchField |
674 andHeaderView:(UIView*)headerView { | 675 andHeaderView:(UIView*)headerView { |
675 _doodleTopMarginConstraint.reset([[logoView.topAnchor | 676 _doodleTopMarginConstraint = [logoView.topAnchor |
676 constraintEqualToAnchor:headerView.topAnchor | 677 constraintEqualToAnchor:headerView.topAnchor |
677 constant:content_suggestions::doodleTopMargin()] retain]); | 678 constant:content_suggestions::doodleTopMargin()]; |
678 _doodleHeightConstraint.reset([[logoView.heightAnchor | 679 _doodleHeightConstraint = [logoView.heightAnchor |
679 constraintEqualToConstant:content_suggestions::doodleHeight( | 680 constraintEqualToConstant:content_suggestions::doodleHeight( |
680 self.logoIsShowing)] retain]); | 681 self.logoIsShowing)]; |
681 _searchFieldWidthConstraint.reset([[searchField.widthAnchor | 682 _searchFieldWidthConstraint = [searchField.widthAnchor |
682 constraintEqualToConstant:content_suggestions::searchFieldWidth( | 683 constraintEqualToConstant:content_suggestions::searchFieldWidth( |
683 [self viewWidth])] retain]); | 684 [self viewWidth])]; |
684 _searchFieldHeightConstraint.reset([[searchField.heightAnchor | 685 _searchFieldHeightConstraint = [searchField.heightAnchor |
685 constraintEqualToConstant:content_suggestions::kSearchFieldHeight] | 686 constraintEqualToConstant:content_suggestions::kSearchFieldHeight]; |
686 retain]); | 687 _searchFieldTopMarginConstraint = [searchField.topAnchor |
687 _searchFieldTopMarginConstraint.reset([[searchField.topAnchor | |
688 constraintEqualToAnchor:logoView.bottomAnchor | 688 constraintEqualToAnchor:logoView.bottomAnchor |
689 constant:content_suggestions::searchFieldTopMargin()] | 689 constant:content_suggestions::searchFieldTopMargin()]; |
690 retain]); | |
691 [NSLayoutConstraint activateConstraints:@[ | 690 [NSLayoutConstraint activateConstraints:@[ |
692 _doodleTopMarginConstraint, | 691 _doodleTopMarginConstraint, |
693 _doodleHeightConstraint.get(), | 692 _doodleHeightConstraint, |
694 _searchFieldWidthConstraint.get(), | 693 _searchFieldWidthConstraint, |
695 _searchFieldHeightConstraint.get(), | 694 _searchFieldHeightConstraint, |
696 _searchFieldTopMarginConstraint.get(), | 695 _searchFieldTopMarginConstraint, |
697 [logoView.widthAnchor constraintEqualToAnchor:headerView.widthAnchor], | 696 [logoView.widthAnchor constraintEqualToAnchor:headerView.widthAnchor], |
698 [logoView.leadingAnchor constraintEqualToAnchor:headerView.leadingAnchor], | 697 [logoView.leadingAnchor constraintEqualToAnchor:headerView.leadingAnchor], |
699 [searchField.centerXAnchor | 698 [searchField.centerXAnchor |
700 constraintEqualToAnchor:headerView.centerXAnchor], | 699 constraintEqualToAnchor:headerView.centerXAnchor], |
701 ]]; | 700 ]]; |
702 } | 701 } |
703 | 702 |
704 - (void)updateConstraintsForWidth:(CGFloat)width { | 703 - (void)updateConstraintsForWidth:(CGFloat)width { |
705 [_promoHeaderView | 704 [_promoHeaderView |
706 setSideMargin:content_suggestions::centeredTilesMarginForWidth(width) | 705 setSideMargin:content_suggestions::centeredTilesMarginForWidth(width) |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 - (void)collectionView:(UICollectionView*)collectionView | 760 - (void)collectionView:(UICollectionView*)collectionView |
762 didSelectItemAtIndexPath:(NSIndexPath*)indexPath { | 761 didSelectItemAtIndexPath:(NSIndexPath*)indexPath { |
763 MostVisitedCell* cell = | 762 MostVisitedCell* cell = |
764 (MostVisitedCell*)[collectionView cellForItemAtIndexPath:indexPath]; | 763 (MostVisitedCell*)[collectionView cellForItemAtIndexPath:indexPath]; |
765 | 764 |
766 // Keep the UICollectionView alive for one second while the screen | 765 // Keep the UICollectionView alive for one second while the screen |
767 // reader does its thing. | 766 // reader does its thing. |
768 // TODO(jif): This needs a radar, since it is almost certainly a | 767 // TODO(jif): This needs a radar, since it is almost certainly a |
769 // UIKit accessibility bug. crbug.com/529271 | 768 // UIKit accessibility bug. crbug.com/529271 |
770 if (UIAccessibilityIsVoiceOverRunning()) { | 769 if (UIAccessibilityIsVoiceOverRunning()) { |
771 UICollectionView* blockView = [_mostVisitedView retain]; | 770 __block UICollectionView* blockView = _mostVisitedView; |
772 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, | 771 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, |
773 static_cast<int64_t>(1 * NSEC_PER_SEC)), | 772 static_cast<int64_t>(1 * NSEC_PER_SEC)), |
774 dispatch_get_main_queue(), ^{ | 773 dispatch_get_main_queue(), ^{ |
775 [blockView release]; | 774 blockView = nil; |
776 }); | 775 }); |
777 } | 776 } |
778 | 777 |
779 const NSUInteger visitedIndex = indexPath.row; | 778 const NSUInteger visitedIndex = indexPath.row; |
780 [self blurOmnibox]; | 779 [self blurOmnibox]; |
781 DCHECK(visitedIndex < [self numberOfItems]); | 780 DCHECK(visitedIndex < [self numberOfItems]); |
782 [self.dataSource logMostVisitedClick:visitedIndex tileType:cell.tileType]; | 781 [self.dataSource logMostVisitedClick:visitedIndex tileType:cell.tileType]; |
783 [self.dispatcher loadURL:[self urlForIndex:visitedIndex] | 782 [self.dispatcher loadURL:[self urlForIndex:visitedIndex] |
784 referrer:web::Referrer() | 783 referrer:web::Referrer() |
785 transition:ui::PAGE_TRANSITION_AUTO_BOOKMARK | 784 transition:ui::PAGE_TRANSITION_AUTO_BOOKMARK |
786 rendererInitiated:NO]; | 785 rendererInitiated:NO]; |
787 } | 786 } |
788 | 787 |
789 #pragma mark - UICollectionViewDataSource | 788 #pragma mark - UICollectionViewDataSource |
790 | 789 |
791 - (UICollectionReusableView*)collectionView:(UICollectionView*)collectionView | 790 - (UICollectionReusableView*)collectionView:(UICollectionView*)collectionView |
792 viewForSupplementaryElementOfKind:(NSString*)kind | 791 viewForSupplementaryElementOfKind:(NSString*)kind |
793 atIndexPath:(NSIndexPath*)indexPath { | 792 atIndexPath:(NSIndexPath*)indexPath { |
794 DCHECK(kind == UICollectionElementKindSectionHeader); | 793 DCHECK(kind == UICollectionElementKindSectionHeader); |
795 | 794 |
796 if (indexPath.section == SectionWithOmnibox) { | 795 if (indexPath.section == SectionWithOmnibox) { |
797 UICollectionReusableView* reusableView = | 796 UICollectionReusableView* reusableView = |
798 [collectionView dequeueReusableSupplementaryViewOfKind: | 797 [collectionView dequeueReusableSupplementaryViewOfKind: |
799 UICollectionElementKindSectionHeader | 798 UICollectionElementKindSectionHeader |
800 withReuseIdentifier:@"header" | 799 withReuseIdentifier:@"header" |
801 forIndexPath:indexPath]; | 800 forIndexPath:indexPath]; |
802 if (!_headerView) { | 801 if (!_headerView) { |
803 _headerView.reset([[NewTabPageHeaderView alloc] init]); | 802 _headerView = [[NewTabPageHeaderView alloc] init]; |
804 [_headerView addSubview:[self.logoVendor view]]; | 803 [_headerView addSubview:[self.logoVendor view]]; |
805 [_headerView addSubview:_searchTapTarget]; | 804 [_headerView addSubview:_searchTapTarget]; |
806 self.logoVendor.view.translatesAutoresizingMaskIntoConstraints = NO; | 805 self.logoVendor.view.translatesAutoresizingMaskIntoConstraints = NO; |
807 [_searchTapTarget setTranslatesAutoresizingMaskIntoConstraints:NO]; | 806 [_searchTapTarget setTranslatesAutoresizingMaskIntoConstraints:NO]; |
808 | 807 |
809 [self addConstraintsForLogoView:self.logoVendor.view | 808 [self addConstraintsForLogoView:self.logoVendor.view |
810 searchField:_searchTapTarget | 809 searchField:_searchTapTarget |
811 andHeaderView:_headerView]; | 810 andHeaderView:_headerView]; |
812 | 811 |
813 [_headerView addViewsToSearchField:_searchTapTarget]; | 812 [_headerView addViewsToSearchField:_searchTapTarget]; |
(...skipping 16 matching lines...) Expand all Loading... |
830 return reusableView; | 829 return reusableView; |
831 } | 830 } |
832 | 831 |
833 if (indexPath.section == SectionWithMostVisited) { | 832 if (indexPath.section == SectionWithMostVisited) { |
834 UICollectionReusableView* reusableView = | 833 UICollectionReusableView* reusableView = |
835 [collectionView dequeueReusableSupplementaryViewOfKind: | 834 [collectionView dequeueReusableSupplementaryViewOfKind: |
836 UICollectionElementKindSectionHeader | 835 UICollectionElementKindSectionHeader |
837 withReuseIdentifier:@"header" | 836 withReuseIdentifier:@"header" |
838 forIndexPath:indexPath]; | 837 forIndexPath:indexPath]; |
839 if (!_promoHeaderView) { | 838 if (!_promoHeaderView) { |
840 _promoHeaderView.reset([[WhatsNewHeaderView alloc] init]); | 839 _promoHeaderView = [[WhatsNewHeaderView alloc] init]; |
841 [_promoHeaderView | 840 [_promoHeaderView |
842 setSideMargin:content_suggestions::centeredTilesMarginForWidth( | 841 setSideMargin:content_suggestions::centeredTilesMarginForWidth( |
843 [self viewWidth]) | 842 [self viewWidth]) |
844 forWidth:[self viewWidth]]; | 843 forWidth:[self viewWidth]]; |
845 [_promoHeaderView setDelegate:self]; | 844 [_promoHeaderView setDelegate:self]; |
846 if (self.promoCanShow) { | 845 if (self.promoCanShow) { |
847 [_promoHeaderView setText:self.promoText]; | 846 [_promoHeaderView setText:self.promoText]; |
848 [_promoHeaderView setIcon:self.promoIcon]; | 847 [_promoHeaderView setIcon:self.promoIcon]; |
849 [self.dataSource promoViewed]; | 848 [self.dataSource promoViewed]; |
850 } | 849 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 } | 896 } |
898 return cell; | 897 return cell; |
899 } | 898 } |
900 | 899 |
901 const ntp_tiles::NTPTile& ntpTile = | 900 const ntp_tiles::NTPTile& ntpTile = |
902 [self.dataSource mostVisitedAtIndex:indexPath.row]; | 901 [self.dataSource mostVisitedAtIndex:indexPath.row]; |
903 NSString* title = base::SysUTF16ToNSString(ntpTile.title); | 902 NSString* title = base::SysUTF16ToNSString(ntpTile.title); |
904 | 903 |
905 [cell setupWithURL:ntpTile.url title:title dataSource:self.dataSource]; | 904 [cell setupWithURL:ntpTile.url title:title dataSource:self.dataSource]; |
906 | 905 |
907 base::scoped_nsobject<UILongPressGestureRecognizer> longPress( | 906 UILongPressGestureRecognizer* longPress = |
908 [[UILongPressGestureRecognizer alloc] | 907 [[UILongPressGestureRecognizer alloc] |
909 initWithTarget:self | 908 initWithTarget:self |
910 action:@selector(handleMostVisitedLongPress:)]); | 909 action:@selector(handleMostVisitedLongPress:)]; |
911 [cell addGestureRecognizer:longPress]; | 910 [cell addGestureRecognizer:longPress]; |
912 | 911 |
913 return cell; | 912 return cell; |
914 } | 913 } |
915 | 914 |
916 #pragma mark - Context Menu | 915 #pragma mark - Context Menu |
917 | 916 |
918 // Called when a user does a long press on a most visited item. | 917 // Called when a user does a long press on a most visited item. |
919 - (void)handleMostVisitedLongPress:(UILongPressGestureRecognizer*)sender { | 918 - (void)handleMostVisitedLongPress:(UILongPressGestureRecognizer*)sender { |
920 if (sender.state == UIGestureRecognizerStateBegan) { | 919 if (sender.state == UIGestureRecognizerStateBegan) { |
921 // Only one long press at a time. | 920 // Only one long press at a time. |
922 if ([_contextMenuCoordinator isVisible]) { | 921 if ([_contextMenuCoordinator isVisible]) { |
923 return; | 922 return; |
924 } | 923 } |
925 | 924 |
926 NSIndexPath* indexPath = [_mostVisitedView | 925 NSIndexPath* indexPath = [_mostVisitedView |
927 indexPathForCell:static_cast<UICollectionViewCell*>(sender.view)]; | 926 indexPathForCell:static_cast<UICollectionViewCell*>(sender.view)]; |
928 const NSUInteger index = indexPath.row; | 927 const NSUInteger index = indexPath.row; |
929 | 928 |
930 // A long press occured on one of the most visited button. Popup a context | 929 // A long press occured on one of the most visited button. Popup a context |
931 // menu. | 930 // menu. |
932 DCHECK(index < [self numberOfItems]); | 931 DCHECK(index < [self numberOfItems]); |
933 | 932 |
934 web::ContextMenuParams params; | 933 web::ContextMenuParams params; |
935 // Get view coordinates in local space. | 934 // Get view coordinates in local space. |
936 params.location = [sender locationInView:self.view]; | 935 params.location = [sender locationInView:self.view]; |
937 params.view.reset([self.view retain]); | 936 params.view.reset(self.view); |
938 | 937 |
939 // Present sheet/popover using controller that is added to view hierarchy. | 938 // Present sheet/popover using controller that is added to view hierarchy. |
940 UIViewController* topController = [params.view window].rootViewController; | 939 UIViewController* topController = [params.view window].rootViewController; |
941 while (topController.presentedViewController) | 940 while (topController.presentedViewController) |
942 topController = topController.presentedViewController; | 941 topController = topController.presentedViewController; |
943 | 942 |
944 _contextMenuCoordinator.reset([[ContextMenuCoordinator alloc] | 943 _contextMenuCoordinator = |
945 initWithBaseViewController:topController | 944 [[ContextMenuCoordinator alloc] initWithBaseViewController:topController |
946 params:params]); | 945 params:params]; |
947 | 946 |
948 ProceduralBlock action; | 947 ProceduralBlock action; |
949 | 948 |
950 // Open In New Tab. | 949 // Open In New Tab. |
951 GURL url = [self urlForIndex:index]; | 950 GURL url = [self urlForIndex:index]; |
952 base::WeakNSObject<GoogleLandingViewController> weakSelf(self); | 951 __weak GoogleLandingViewController* weakSelf = self; |
953 action = ^{ | 952 action = ^{ |
954 base::scoped_nsobject<GoogleLandingViewController> strongSelf( | 953 GoogleLandingViewController* strongSelf = weakSelf; |
955 [weakSelf retain]); | |
956 if (!strongSelf) | 954 if (!strongSelf) |
957 return; | 955 return; |
958 MostVisitedCell* cell = (MostVisitedCell*)sender.view; | 956 MostVisitedCell* cell = (MostVisitedCell*)sender.view; |
959 [[strongSelf dataSource] logMostVisitedClick:index | 957 [[strongSelf dataSource] logMostVisitedClick:index |
960 tileType:cell.tileType]; | 958 tileType:cell.tileType]; |
961 [[strongSelf dispatcher] webPageOrderedOpen:url | 959 [[strongSelf dispatcher] webPageOrderedOpen:url |
962 referrer:web::Referrer() | 960 referrer:web::Referrer() |
963 inBackground:YES | 961 inBackground:YES |
964 appendTo:kCurrentTab]; | 962 appendTo:kCurrentTab]; |
965 }; | 963 }; |
966 [_contextMenuCoordinator | 964 [_contextMenuCoordinator |
967 addItemWithTitle:l10n_util::GetNSStringWithFixup( | 965 addItemWithTitle:l10n_util::GetNSStringWithFixup( |
968 IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB) | 966 IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB) |
969 action:action]; | 967 action:action]; |
970 | 968 |
971 // Open in Incognito Tab. | 969 // Open in Incognito Tab. |
972 action = ^{ | 970 action = ^{ |
973 base::scoped_nsobject<GoogleLandingViewController> strongSelf( | 971 GoogleLandingViewController* strongSelf = weakSelf; |
974 [weakSelf retain]); | |
975 if (!strongSelf) | 972 if (!strongSelf) |
976 return; | 973 return; |
977 MostVisitedCell* cell = (MostVisitedCell*)sender.view; | 974 MostVisitedCell* cell = (MostVisitedCell*)sender.view; |
978 [[strongSelf dataSource] logMostVisitedClick:index | 975 [[strongSelf dataSource] logMostVisitedClick:index |
979 tileType:cell.tileType]; | 976 tileType:cell.tileType]; |
980 [[strongSelf dispatcher] webPageOrderedOpen:url | 977 [[strongSelf dispatcher] webPageOrderedOpen:url |
981 referrer:web::Referrer() | 978 referrer:web::Referrer() |
982 inIncognito:YES | 979 inIncognito:YES |
983 inBackground:NO | 980 inBackground:NO |
984 appendTo:kCurrentTab]; | 981 appendTo:kCurrentTab]; |
985 }; | 982 }; |
986 [_contextMenuCoordinator | 983 [_contextMenuCoordinator |
987 addItemWithTitle:l10n_util::GetNSStringWithFixup( | 984 addItemWithTitle:l10n_util::GetNSStringWithFixup( |
988 IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB) | 985 IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB) |
989 action:action]; | 986 action:action]; |
990 | 987 |
991 // Remove the most visited url. | 988 // Remove the most visited url. |
992 NSString* title = | 989 NSString* title = |
993 l10n_util::GetNSStringWithFixup(IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK); | 990 l10n_util::GetNSStringWithFixup(IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK); |
994 action = ^{ | 991 action = ^{ |
995 base::scoped_nsobject<GoogleLandingViewController> strongSelf( | 992 GoogleLandingViewController* strongSelf = weakSelf; |
996 [weakSelf retain]); | |
997 // Early return if the controller has been deallocated. | 993 // Early return if the controller has been deallocated. |
998 if (!strongSelf) | 994 if (!strongSelf) |
999 return; | 995 return; |
1000 base::RecordAction(UserMetricsAction("MostVisited_UrlBlacklisted")); | 996 base::RecordAction(UserMetricsAction("MostVisited_UrlBlacklisted")); |
1001 [[strongSelf dataSource] addBlacklistedURL:url]; | 997 [[strongSelf dataSource] addBlacklistedURL:url]; |
1002 [strongSelf showMostVisitedUndoForURL:net::NSURLWithGURL(url)]; | 998 [strongSelf showMostVisitedUndoForURL:net::NSURLWithGURL(url)]; |
1003 }; | 999 }; |
1004 [_contextMenuCoordinator addItemWithTitle:title action:action]; | 1000 [_contextMenuCoordinator addItemWithTitle:title action:action]; |
1005 | 1001 |
1006 [_contextMenuCoordinator start]; | 1002 [_contextMenuCoordinator start]; |
1007 | 1003 |
1008 if (IsIPadIdiom()) | 1004 if (IsIPadIdiom()) |
1009 [self blurOmnibox]; | 1005 [self blurOmnibox]; |
1010 } | 1006 } |
1011 } | 1007 } |
1012 | 1008 |
1013 - (void)showMostVisitedUndoForURL:(NSURL*)url { | 1009 - (void)showMostVisitedUndoForURL:(NSURL*)url { |
1014 _deletedUrl.reset([url retain]); | 1010 _deletedUrl = url; |
1015 | 1011 |
1016 MDCSnackbarMessageAction* action = | 1012 MDCSnackbarMessageAction* action = [[MDCSnackbarMessageAction alloc] init]; |
1017 [[[MDCSnackbarMessageAction alloc] init] autorelease]; | 1013 __weak GoogleLandingViewController* weakSelf = self; |
1018 base::WeakNSObject<GoogleLandingViewController> weakSelf(self); | |
1019 action.handler = ^{ | 1014 action.handler = ^{ |
1020 base::scoped_nsobject<GoogleLandingViewController> strongSelf( | 1015 GoogleLandingViewController* strongSelf = weakSelf; |
1021 [weakSelf retain]); | |
1022 if (!strongSelf) | 1016 if (!strongSelf) |
1023 return; | 1017 return; |
1024 [[strongSelf dataSource] | 1018 [[strongSelf dataSource] |
1025 removeBlacklistedURL:net::GURLWithNSURL(_deletedUrl)]; | 1019 removeBlacklistedURL:net::GURLWithNSURL(_deletedUrl)]; |
1026 }; | 1020 }; |
1027 action.title = l10n_util::GetNSString(IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE); | 1021 action.title = l10n_util::GetNSString(IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE); |
1028 action.accessibilityIdentifier = @"Undo"; | 1022 action.accessibilityIdentifier = @"Undo"; |
1029 | 1023 |
1030 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); | 1024 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); |
1031 MDCSnackbarMessage* message = [MDCSnackbarMessage | 1025 MDCSnackbarMessage* message = [MDCSnackbarMessage |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 - (BOOL)animateHeader { | 1230 - (BOOL)animateHeader { |
1237 return _animateHeader; | 1231 return _animateHeader; |
1238 } | 1232 } |
1239 | 1233 |
1240 #pragma mark - OverscrollActionsControllerDelegate | 1234 #pragma mark - OverscrollActionsControllerDelegate |
1241 | 1235 |
1242 - (void)overscrollActionsController:(OverscrollActionsController*)controller | 1236 - (void)overscrollActionsController:(OverscrollActionsController*)controller |
1243 didTriggerAction:(OverscrollAction)action { | 1237 didTriggerAction:(OverscrollAction)action { |
1244 switch (action) { | 1238 switch (action) { |
1245 case OverscrollAction::NEW_TAB: { | 1239 case OverscrollAction::NEW_TAB: { |
1246 base::scoped_nsobject<GenericChromeCommand> command( | 1240 GenericChromeCommand* command = |
1247 [[GenericChromeCommand alloc] initWithTag:IDC_NEW_TAB]); | 1241 [[GenericChromeCommand alloc] initWithTag:IDC_NEW_TAB]; |
1248 [[self view] chromeExecuteCommand:command]; | 1242 [[self view] chromeExecuteCommand:command]; |
1249 } break; | 1243 } break; |
1250 case OverscrollAction::CLOSE_TAB: { | 1244 case OverscrollAction::CLOSE_TAB: { |
1251 base::scoped_nsobject<GenericChromeCommand> command( | 1245 GenericChromeCommand* command = |
1252 [[GenericChromeCommand alloc] initWithTag:IDC_CLOSE_TAB]); | 1246 [[GenericChromeCommand alloc] initWithTag:IDC_CLOSE_TAB]; |
1253 [[self view] chromeExecuteCommand:command]; | 1247 [[self view] chromeExecuteCommand:command]; |
1254 } break; | 1248 } break; |
1255 case OverscrollAction::REFRESH: | 1249 case OverscrollAction::REFRESH: |
1256 [self reload]; | 1250 [self reload]; |
1257 break; | 1251 break; |
1258 case OverscrollAction::NONE: | 1252 case OverscrollAction::NONE: |
1259 NOTREACHED(); | 1253 NOTREACHED(); |
1260 break; | 1254 break; |
1261 } | 1255 } |
1262 } | 1256 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 - (void)setCanGoForward:(BOOL)canGoForward { | 1322 - (void)setCanGoForward:(BOOL)canGoForward { |
1329 _canGoForward = canGoForward; | 1323 _canGoForward = canGoForward; |
1330 [_headerView setCanGoForward:self.canGoForward]; | 1324 [_headerView setCanGoForward:self.canGoForward]; |
1331 } | 1325 } |
1332 | 1326 |
1333 - (void)setCanGoBack:(BOOL)canGoBack { | 1327 - (void)setCanGoBack:(BOOL)canGoBack { |
1334 _canGoBack = canGoBack; | 1328 _canGoBack = canGoBack; |
1335 [_headerView setCanGoBack:self.canGoBack]; | 1329 [_headerView setCanGoBack:self.canGoBack]; |
1336 } | 1330 } |
1337 @end | 1331 @end |
OLD | NEW |