OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 #include "ios/chrome/browser/ui/contextual_search/contextual_search_results_view
.h" | 5 #include "ios/chrome/browser/ui/contextual_search/contextual_search_results_view
.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #import "base/ios/weak_nsobject.h" | |
10 #include "base/mac/scoped_nsobject.h" | |
11 #import "ios/chrome/browser/tabs/tab.h" | 9 #import "ios/chrome/browser/tabs/tab.h" |
12 #import "ios/chrome/browser/ui/contextual_search/contextual_search_metrics.h" | 10 #import "ios/chrome/browser/ui/contextual_search/contextual_search_metrics.h" |
13 #import "ios/chrome/browser/ui/contextual_search/contextual_search_panel_view.h" | 11 #import "ios/chrome/browser/ui/contextual_search/contextual_search_panel_view.h" |
14 #import "ios/chrome/browser/ui/contextual_search/contextual_search_web_state_obs
erver.h" | 12 #import "ios/chrome/browser/ui/contextual_search/contextual_search_web_state_obs
erver.h" |
15 #import "ios/chrome/common/material_timing.h" | 13 #import "ios/chrome/common/material_timing.h" |
16 #include "ios/web/public/load_committed_details.h" | 14 #include "ios/web/public/load_committed_details.h" |
17 #import "ios/web/public/web_state/crw_web_view_proxy.h" | 15 #import "ios/web/public/web_state/crw_web_view_proxy.h" |
18 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" | 16 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" |
19 #import "ios/web/public/web_state/ui/crw_native_content_provider.h" | 17 #import "ios/web/public/web_state/ui/crw_native_content_provider.h" |
20 #import "ios/web/web_state/ui/crw_web_controller.h" | 18 #import "ios/web/web_state/ui/crw_web_controller.h" |
21 | 19 |
| 20 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 21 #error "This file requires ARC support." |
| 22 #endif |
| 23 |
22 namespace { | 24 namespace { |
23 enum SearchResultsViewVisibility { OFFSCREEN, PRELOAD, VISIBLE }; | 25 enum SearchResultsViewVisibility { OFFSCREEN, PRELOAD, VISIBLE }; |
24 } | 26 } |
25 | 27 |
26 @interface ContextualSearchResultsView ()<ContextualSearchWebStateDelegate, | 28 @interface ContextualSearchResultsView ()<ContextualSearchWebStateDelegate, |
27 CRWNativeContentProvider> | 29 CRWNativeContentProvider> |
28 | 30 |
29 // Can the search results be scrolled currently? | 31 // Can the search results be scrolled currently? |
30 @property(nonatomic, assign, getter=isScrollEnabled) BOOL scrollEnabled; | 32 @property(nonatomic, assign, getter=isScrollEnabled) BOOL scrollEnabled; |
31 @end | 33 @end |
32 | 34 |
33 @implementation ContextualSearchResultsView { | 35 @implementation ContextualSearchResultsView { |
34 base::WeakNSProtocol<id<ContextualSearchTabPromoter>> _promoter; | |
35 base::WeakNSProtocol<id<ContextualSearchPreloadChecker>> _preloadChecker; | |
36 std::unique_ptr<ContextualSearchWebStateObserver> _webStateObserver; | 36 std::unique_ptr<ContextualSearchWebStateObserver> _webStateObserver; |
37 | 37 |
38 // Tab that loads the search results. | 38 // Tab that loads the search results. |
39 base::scoped_nsobject<Tab> _tab; | 39 Tab* _tab; |
40 | 40 |
41 // Access to the search tab's web view proxy. | 41 // Access to the search tab's web view proxy. |
42 base::scoped_nsprotocol<id<CRWWebViewProxy>> _webViewProxy; | 42 id<CRWWebViewProxy> _webViewProxy; |
43 | 43 |
44 BOOL _loaded; | 44 BOOL _loaded; |
45 BOOL _displayed; | 45 BOOL _displayed; |
46 BOOL _loadingError; | 46 BOOL _loadingError; |
47 BOOL _waitingForInitialSearchTabLoad; | 47 BOOL _waitingForInitialSearchTabLoad; |
48 BOOL _loadInProgress; | 48 BOOL _loadInProgress; |
49 BOOL _shouldScroll; | 49 BOOL _shouldScroll; |
50 | 50 |
51 BOOL _preloadEnabled; | 51 BOOL _preloadEnabled; |
52 | 52 |
53 SearchResultsViewVisibility _visibility; | 53 SearchResultsViewVisibility _visibility; |
54 | 54 |
55 // Time of starting a search results page load. | 55 // Time of starting a search results page load. |
56 base::Time _loadStartTime; | 56 base::Time _loadStartTime; |
57 } | 57 } |
58 | 58 |
59 @synthesize active = _active; | 59 @synthesize active = _active; |
60 @synthesize opener = _opener; | 60 @synthesize opener = _opener; |
| 61 @synthesize promoter = _promoter; |
| 62 @synthesize preloadChecker = _preloadChecker; |
61 | 63 |
62 - (instancetype)initWithFrame:(CGRect)frame { | 64 - (instancetype)initWithFrame:(CGRect)frame { |
63 if ((self = [super initWithFrame:frame])) { | 65 if ((self = [super initWithFrame:frame])) { |
64 self.translatesAutoresizingMaskIntoConstraints = NO; | 66 self.translatesAutoresizingMaskIntoConstraints = NO; |
65 self.backgroundColor = [UIColor whiteColor]; | 67 self.backgroundColor = [UIColor whiteColor]; |
66 self.accessibilityIdentifier = @"contextualSearchResultsView"; | 68 self.accessibilityIdentifier = @"contextualSearchResultsView"; |
67 self.clipsToBounds = YES; | 69 self.clipsToBounds = YES; |
68 _webStateObserver.reset(new ContextualSearchWebStateObserver(self)); | 70 _webStateObserver.reset(new ContextualSearchWebStateObserver(self)); |
69 _visibility = OFFSCREEN; | 71 _visibility = OFFSCREEN; |
70 } | 72 } |
(...skipping 11 matching lines...) Expand all Loading... |
82 [[_webViewProxy scrollViewProxy] setBounces:NO]; | 84 [[_webViewProxy scrollViewProxy] setBounces:NO]; |
83 } | 85 } |
84 | 86 |
85 #pragma mark - public properties | 87 #pragma mark - public properties |
86 | 88 |
87 - (id<ContextualSearchTabPromoter>)promoter { | 89 - (id<ContextualSearchTabPromoter>)promoter { |
88 return _promoter; | 90 return _promoter; |
89 } | 91 } |
90 | 92 |
91 - (void)setPromoter:(id<ContextualSearchTabPromoter>)promoter { | 93 - (void)setPromoter:(id<ContextualSearchTabPromoter>)promoter { |
92 _promoter.reset(promoter); | 94 _promoter = promoter; |
93 } | 95 } |
94 | 96 |
95 - (id<ContextualSearchPreloadChecker>)preloadChecker { | 97 - (id<ContextualSearchPreloadChecker>)preloadChecker { |
96 return _preloadChecker; | 98 return _preloadChecker; |
97 } | 99 } |
98 | 100 |
99 - (void)setPreloadChecker:(id<ContextualSearchPreloadChecker>)preloadChecker { | 101 - (void)setPreloadChecker:(id<ContextualSearchPreloadChecker>)preloadChecker { |
100 _preloadChecker.reset(preloadChecker); | 102 _preloadChecker = preloadChecker; |
101 } | 103 } |
102 | 104 |
103 - (BOOL)contentVisible { | 105 - (BOOL)contentVisible { |
104 return _loaded && _visibility == VISIBLE; | 106 return _loaded && _visibility == VISIBLE; |
105 } | 107 } |
106 | 108 |
107 - (void)setActive:(BOOL)active { | 109 - (void)setActive:(BOOL)active { |
108 if (active) { | 110 if (active) { |
109 // Start watching the embedded Tab's web activity. | 111 // Start watching the embedded Tab's web activity. |
110 _webStateObserver->ObserveWebState([_tab webState]); | 112 _webStateObserver->ObserveWebState([_tab webState]); |
111 [[_tab webController] setShouldSuppressDialogs:NO]; | 113 [[_tab webController] setShouldSuppressDialogs:NO]; |
112 _webViewProxy.reset([[[_tab webController] webViewProxy] retain]); | 114 _webViewProxy = [[_tab webController] webViewProxy]; |
113 [[_webViewProxy scrollViewProxy] setBounces:NO]; | 115 [[_webViewProxy scrollViewProxy] setBounces:NO]; |
114 } else { | 116 } else { |
115 // Stop watching the embedded Tab's web activity. | 117 // Stop watching the embedded Tab's web activity. |
116 _webStateObserver->ObserveWebState(nullptr); | 118 _webStateObserver->ObserveWebState(nullptr); |
117 _webViewProxy.reset(nil); | 119 _webViewProxy = nil; |
118 } | 120 } |
119 | 121 |
120 _active = active; | 122 _active = active; |
121 } | 123 } |
122 | 124 |
123 #pragma mark - public methods | 125 #pragma mark - public methods |
124 | 126 |
125 - (void)scrollToTopAnimated:(BOOL)animated { | 127 - (void)scrollToTopAnimated:(BOOL)animated { |
126 [[_webViewProxy scrollViewProxy] setBounces:YES]; | 128 [[_webViewProxy scrollViewProxy] setBounces:YES]; |
127 // Scroll the search tab's view to the top. | 129 // Scroll the search tab's view to the top. |
(...skipping 13 matching lines...) Expand all Loading... |
141 | 143 |
142 ui::PageTransition transition = ui::PAGE_TRANSITION_FROM_ADDRESS_BAR; | 144 ui::PageTransition transition = ui::PAGE_TRANSITION_FROM_ADDRESS_BAR; |
143 Tab* tab = [Tab newPreloadingTabWithBrowserState:self.opener.browserState | 145 Tab* tab = [Tab newPreloadingTabWithBrowserState:self.opener.browserState |
144 url:url | 146 url:url |
145 referrer:web::Referrer() | 147 referrer:web::Referrer() |
146 transition:transition | 148 transition:transition |
147 provider:self | 149 provider:self |
148 opener:self.opener | 150 opener:self.opener |
149 desktopUserAgent:false | 151 desktopUserAgent:false |
150 configuration:searchTabConfiguration]; | 152 configuration:searchTabConfiguration]; |
151 _tab.reset([tab retain]); | 153 _tab = tab; |
152 // Don't actually start the page load yet -- that happens in -loadTab | 154 // Don't actually start the page load yet -- that happens in -loadTab |
153 | 155 |
154 _preloadEnabled = preloadEnabled; | 156 _preloadEnabled = preloadEnabled; |
155 [self loadPendingSearchIfPossible]; | 157 [self loadPendingSearchIfPossible]; |
156 } | 158 } |
157 | 159 |
158 - (Tab*)releaseTab { | 160 - (Tab*)releaseTab { |
159 [self disconnectTab]; | 161 [self disconnectTab]; |
160 // Allow the search tab to be sized by autoresizing mask again. | 162 // Allow the search tab to be sized by autoresizing mask again. |
161 [[_tab view] setTranslatesAutoresizingMaskIntoConstraints:YES]; | 163 [[_tab view] setTranslatesAutoresizingMaskIntoConstraints:YES]; |
162 return [_tab.release() autorelease]; | 164 Tab* tab = _tab; |
| 165 _tab = nil; |
| 166 return tab; |
163 } | 167 } |
164 | 168 |
165 - (void)recordFinishedSearchChained:(BOOL)chained { | 169 - (void)recordFinishedSearchChained:(BOOL)chained { |
166 base::TimeDelta duration = base::Time::Now() - _loadStartTime; | 170 base::TimeDelta duration = base::Time::Now() - _loadStartTime; |
167 ContextualSearch::RecordDuration(self.contentVisible, chained, duration); | 171 ContextualSearch::RecordDuration(self.contentVisible, chained, duration); |
168 } | 172 } |
169 | 173 |
170 #pragma mark - private methods | 174 #pragma mark - private methods |
171 | 175 |
172 - (void)disconnectTab { | 176 - (void)disconnectTab { |
173 [[_tab view] removeFromSuperview]; | 177 [[_tab view] removeFromSuperview]; |
174 [[_tab webController] setNativeProvider:nil]; | 178 [[_tab webController] setNativeProvider:nil]; |
175 self.active = NO; | 179 self.active = NO; |
176 _webViewProxy.reset(); | 180 _webViewProxy = nil; |
177 } | 181 } |
178 | 182 |
179 - (void)cancelLoad { | 183 - (void)cancelLoad { |
180 [self disconnectTab]; | 184 [self disconnectTab]; |
181 _loadInProgress = NO; | 185 _loadInProgress = NO; |
182 _loaded = NO; | 186 _loaded = NO; |
183 [_tab close]; | 187 [_tab close]; |
184 _tab.reset(); | 188 _tab = nil; |
185 } | 189 } |
186 | 190 |
187 - (void)loadPendingSearchIfPossible { | 191 - (void)loadPendingSearchIfPossible { |
188 // If the search tab hasn't been created, or if it's already loaded, no-op. | 192 // If the search tab hasn't been created, or if it's already loaded, no-op. |
189 if (!_tab.get() || _loadInProgress || self.active || _visibility == OFFSCREEN) | 193 if (!_tab || _loadInProgress || self.active || _visibility == OFFSCREEN) |
190 return; | 194 return; |
191 | 195 |
192 // If this view is in a position where loading would be "preloading", check | 196 // If this view is in a position where loading would be "preloading", check |
193 // if that's allowed. | 197 // if that's allowed. |
194 if (_visibility == PRELOAD && | 198 if (_visibility == PRELOAD && |
195 !([_preloadChecker canPreloadSearchResults] && _preloadEnabled)) { | 199 !([_preloadChecker canPreloadSearchResults] && _preloadEnabled)) { |
196 return; | 200 return; |
197 } | 201 } |
198 [self loadTab]; | 202 [self loadTab]; |
199 } | 203 } |
200 | 204 |
201 - (void)loadTab { | 205 - (void)loadTab { |
202 DCHECK(_tab.get()); | 206 DCHECK(_tab); |
203 // Start observing the search tab. | 207 // Start observing the search tab. |
204 self.active = YES; | 208 self.active = YES; |
205 // TODO(crbug.com/546223): See if |_waitingForInitialSearchTabLoad| and | 209 // TODO(crbug.com/546223): See if |_waitingForInitialSearchTabLoad| and |
206 // |_loadInProgress| can be consolidated. | 210 // |_loadInProgress| can be consolidated. |
207 _waitingForInitialSearchTabLoad = YES; | 211 _waitingForInitialSearchTabLoad = YES; |
208 // Mark the start of the time for the search. | 212 // Mark the start of the time for the search. |
209 _loadStartTime = base::Time::Now(); | 213 _loadStartTime = base::Time::Now(); |
210 // Start the load by asking for the tab's view, but making it hidden. | 214 // Start the load by asking for the tab's view, but making it hidden. |
211 [_tab view].hidden = YES; | 215 [_tab view].hidden = YES; |
212 [self addSubview:[_tab view]]; | 216 [self addSubview:[_tab view]]; |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 withError:error | 357 withError:error |
354 isPost:isPost]; | 358 isPost:isPost]; |
355 | 359 |
356 if ([errorController respondsToSelector:@selector(setScrollEnabled:)]) { | 360 if ([errorController respondsToSelector:@selector(setScrollEnabled:)]) { |
357 [errorController setScrollEnabled:NO]; | 361 [errorController setScrollEnabled:NO]; |
358 } | 362 } |
359 return errorController; | 363 return errorController; |
360 } | 364 } |
361 | 365 |
362 @end | 366 @end |
OLD | NEW |