| 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" | 9 #import "base/ios/weak_nsobject.h" |
| 10 #include "base/mac/scoped_nsobject.h" | 10 #include "base/mac/scoped_nsobject.h" |
| 11 #include "base/memory/ptr_util.h" |
| 12 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 13 #import "ios/chrome/browser/tabs/legacy_tab_helper.h" |
| 11 #import "ios/chrome/browser/tabs/tab.h" | 14 #import "ios/chrome/browser/tabs/tab.h" |
| 15 #import "ios/chrome/browser/tabs/tab_helper_util.h" |
| 12 #import "ios/chrome/browser/ui/contextual_search/contextual_search_metrics.h" | 16 #import "ios/chrome/browser/ui/contextual_search/contextual_search_metrics.h" |
| 13 #import "ios/chrome/browser/ui/contextual_search/contextual_search_panel_view.h" | 17 #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" | 18 #import "ios/chrome/browser/ui/contextual_search/contextual_search_web_state_obs
erver.h" |
| 15 #import "ios/chrome/common/material_timing.h" | 19 #import "ios/chrome/common/material_timing.h" |
| 20 #import "ios/shared/chrome/browser/tabs/web_state_opener.h" |
| 16 #include "ios/web/public/load_committed_details.h" | 21 #include "ios/web/public/load_committed_details.h" |
| 22 #import "ios/web/public/serializable_user_data_manager.h" |
| 17 #import "ios/web/public/web_state/ui/crw_native_content_provider.h" | 23 #import "ios/web/public/web_state/ui/crw_native_content_provider.h" |
| 18 #import "ios/web/public/web_state/ui/crw_web_view_proxy.h" | 24 #import "ios/web/public/web_state/ui/crw_web_view_proxy.h" |
| 19 #import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" | 25 #import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" |
| 26 #import "ios/web/public/web_state/web_state.h" |
| 20 #import "ios/web/web_state/ui/crw_web_controller.h" | 27 #import "ios/web/web_state/ui/crw_web_controller.h" |
| 21 | 28 |
| 22 namespace { | 29 namespace { |
| 23 enum SearchResultsViewVisibility { OFFSCREEN, PRELOAD, VISIBLE }; | 30 enum SearchResultsViewVisibility { OFFSCREEN, PRELOAD, VISIBLE }; |
| 24 } | 31 } |
| 25 | 32 |
| 26 @interface ContextualSearchResultsView ()<ContextualSearchWebStateDelegate, | 33 @interface ContextualSearchResultsView ()<ContextualSearchWebStateDelegate, |
| 27 CRWNativeContentProvider> | 34 CRWNativeContentProvider> |
| 28 | 35 |
| 29 // Can the search results be scrolled currently? | 36 // Can the search results be scrolled currently? |
| 30 @property(nonatomic, assign, getter=isScrollEnabled) BOOL scrollEnabled; | 37 @property(nonatomic, assign, getter=isScrollEnabled) BOOL scrollEnabled; |
| 31 @end | 38 @end |
| 32 | 39 |
| 33 @implementation ContextualSearchResultsView { | 40 @implementation ContextualSearchResultsView { |
| 34 base::WeakNSProtocol<id<ContextualSearchTabPromoter>> _promoter; | 41 base::WeakNSProtocol<id<ContextualSearchTabPromoter>> _promoter; |
| 35 base::WeakNSProtocol<id<ContextualSearchPreloadChecker>> _preloadChecker; | 42 base::WeakNSProtocol<id<ContextualSearchPreloadChecker>> _preloadChecker; |
| 36 std::unique_ptr<ContextualSearchWebStateObserver> _webStateObserver; | 43 std::unique_ptr<ContextualSearchWebStateObserver> _webStateObserver; |
| 37 | 44 |
| 38 // Tab that loads the search results. | 45 // WebState that loads the search results. |
| 39 base::scoped_nsobject<Tab> _tab; | 46 std::unique_ptr<web::WebState> _webState; |
| 47 std::unique_ptr<WebStateOpener> _webStateOpener; |
| 40 | 48 |
| 41 // Access to the search tab's web view proxy. | 49 // Access to the search tab's web view proxy. |
| 42 base::scoped_nsprotocol<id<CRWWebViewProxy>> _webViewProxy; | 50 base::scoped_nsprotocol<id<CRWWebViewProxy>> _webViewProxy; |
| 43 | 51 |
| 44 BOOL _loaded; | 52 BOOL _loaded; |
| 45 BOOL _displayed; | 53 BOOL _displayed; |
| 46 BOOL _loadingError; | 54 BOOL _loadingError; |
| 47 BOOL _waitingForInitialSearchTabLoad; | 55 BOOL _waitingForInitialSearchTabLoad; |
| 48 BOOL _loadInProgress; | 56 BOOL _loadInProgress; |
| 49 BOOL _shouldScroll; | 57 BOOL _shouldScroll; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 - (void)setPreloadChecker:(id<ContextualSearchPreloadChecker>)preloadChecker { | 107 - (void)setPreloadChecker:(id<ContextualSearchPreloadChecker>)preloadChecker { |
| 100 _preloadChecker.reset(preloadChecker); | 108 _preloadChecker.reset(preloadChecker); |
| 101 } | 109 } |
| 102 | 110 |
| 103 - (BOOL)contentVisible { | 111 - (BOOL)contentVisible { |
| 104 return _loaded && _visibility == VISIBLE; | 112 return _loaded && _visibility == VISIBLE; |
| 105 } | 113 } |
| 106 | 114 |
| 107 - (void)setActive:(BOOL)active { | 115 - (void)setActive:(BOOL)active { |
| 108 if (active) { | 116 if (active) { |
| 109 // Start watching the embedded Tab's web activity. | 117 if (_webState) { |
| 110 _webStateObserver->ObserveWebState([_tab webState]); | 118 Tab* tab = LegacyTabHelper::GetTabForWebState(_webState.get()); |
| 111 [[_tab webController] setShouldSuppressDialogs:NO]; | 119 // Start watching the embedded Tab's web activity. |
| 112 _webViewProxy.reset([[[_tab webController] webViewProxy] retain]); | 120 _webStateObserver->ObserveWebState(_webState.get()); |
| 113 [[_webViewProxy scrollViewProxy] setBounces:NO]; | 121 [[tab webController] setShouldSuppressDialogs:NO]; |
| 122 _webViewProxy.reset([[[tab webController] webViewProxy] retain]); |
| 123 [[_webViewProxy scrollViewProxy] setBounces:NO]; |
| 124 } |
| 114 } else { | 125 } else { |
| 115 // Stop watching the embedded Tab's web activity. | 126 // Stop watching the embedded Tab's web activity. |
| 116 _webStateObserver->ObserveWebState(nullptr); | 127 _webStateObserver->ObserveWebState(nullptr); |
| 117 _webViewProxy.reset(nil); | 128 _webViewProxy.reset(nil); |
| 118 } | 129 } |
| 119 | 130 |
| 120 _active = active; | 131 _active = active; |
| 121 } | 132 } |
| 122 | 133 |
| 123 #pragma mark - public methods | 134 #pragma mark - public methods |
| 124 | 135 |
| 125 - (void)scrollToTopAnimated:(BOOL)animated { | 136 - (void)scrollToTopAnimated:(BOOL)animated { |
| 126 [[_webViewProxy scrollViewProxy] setBounces:YES]; | 137 [[_webViewProxy scrollViewProxy] setBounces:YES]; |
| 127 // Scroll the search tab's view to the top. | 138 // Scroll the search tab's view to the top. |
| 128 [[_webViewProxy scrollViewProxy] setContentOffset:CGPointZero | 139 [[_webViewProxy scrollViewProxy] setContentOffset:CGPointZero |
| 129 animated:animated]; | 140 animated:animated]; |
| 130 } | 141 } |
| 131 | 142 |
| 132 - (void)createTabForSearch:(GURL)url preloadEnabled:(BOOL)preloadEnabled { | 143 - (void)createTabForSearch:(GURL)url preloadEnabled:(BOOL)preloadEnabled { |
| 133 DCHECK(self.opener); | 144 DCHECK(self.opener); |
| 134 if (_tab) | 145 if (_webState) |
| 135 [self cancelLoad]; | 146 [self cancelLoad]; |
| 136 | 147 |
| 137 void (^searchTabConfiguration)(Tab*) = ^(Tab* tab) { | 148 _webStateOpener = base::MakeUnique<WebStateOpener>(self.opener.webState); |
| 138 [tab setIsLinkLoadingPrerenderTab:YES]; | 149 web::WebState::CreateParams createParams(self.opener.browserState); |
| 139 [[tab webController] setDelegate:tab]; | 150 _webState = web::WebState::Create(createParams); |
| 140 }; | |
| 141 | 151 |
| 142 ui::PageTransition transition = ui::PAGE_TRANSITION_FROM_ADDRESS_BAR; | 152 AttachTabHelpers(_webState.get()); |
| 143 Tab* tab = [Tab preloadingTabWithBrowserState:self.opener.browserState | 153 Tab* tab = LegacyTabHelper::GetTabForWebState(_webState.get()); |
| 144 url:url | 154 DCHECK(tab); |
| 145 referrer:web::Referrer() | 155 |
| 146 transition:transition | 156 [[tab webController] setNativeProvider:self]; |
| 147 provider:self | 157 [[tab webController] setWebUsageEnabled:YES]; |
| 148 opener:self.opener | 158 [tab setIsLinkLoadingPrerenderTab:YES]; |
| 149 desktopUserAgent:false | 159 [[tab webController] setDelegate:tab]; |
| 150 configuration:searchTabConfiguration]; | 160 |
| 151 _tab.reset([tab retain]); | 161 web::NavigationManager::WebLoadParams loadParams(url); |
| 162 loadParams.transition_type = ui::PAGE_TRANSITION_FROM_ADDRESS_BAR; |
| 163 [[tab webController] loadWithParams:loadParams]; |
| 164 |
| 152 // Don't actually start the page load yet -- that happens in -loadTab | 165 // Don't actually start the page load yet -- that happens in -loadTab |
| 153 | 166 |
| 154 _preloadEnabled = preloadEnabled; | 167 _preloadEnabled = preloadEnabled; |
| 155 [self loadPendingSearchIfPossible]; | 168 [self loadPendingSearchIfPossible]; |
| 156 } | 169 } |
| 157 | 170 |
| 158 - (Tab*)releaseTab { | 171 - (std::unique_ptr<web::WebState>)releaseWebState { |
| 159 [self disconnectTab]; | 172 [self disconnectTab]; |
| 160 // Allow the search tab to be sized by autoresizing mask again. | 173 // Allow the search tab to be sized by autoresizing mask again. |
| 161 [[_tab view] setTranslatesAutoresizingMaskIntoConstraints:YES]; | 174 if (_webState) { |
| 162 return [_tab.release() autorelease]; | 175 Tab* tab = LegacyTabHelper::GetTabForWebState(_webState.get()); |
| 176 [[tab view] setTranslatesAutoresizingMaskIntoConstraints:YES]; |
| 177 } |
| 178 return std::move(_webState); |
| 179 } |
| 180 |
| 181 - (WebStateOpener)webStateOpener { |
| 182 DCHECK(_webStateOpener); |
| 183 return *_webStateOpener; |
| 163 } | 184 } |
| 164 | 185 |
| 165 - (void)recordFinishedSearchChained:(BOOL)chained { | 186 - (void)recordFinishedSearchChained:(BOOL)chained { |
| 166 base::TimeDelta duration = base::Time::Now() - _loadStartTime; | 187 base::TimeDelta duration = base::Time::Now() - _loadStartTime; |
| 167 ContextualSearch::RecordDuration(self.contentVisible, chained, duration); | 188 ContextualSearch::RecordDuration(self.contentVisible, chained, duration); |
| 168 } | 189 } |
| 169 | 190 |
| 170 #pragma mark - private methods | 191 #pragma mark - private methods |
| 171 | 192 |
| 172 - (void)disconnectTab { | 193 - (void)disconnectTab { |
| 173 [[_tab view] removeFromSuperview]; | 194 if (_webState) { |
| 174 [[_tab webController] setNativeProvider:nil]; | 195 Tab* tab = LegacyTabHelper::GetTabForWebState(_webState.get()); |
| 196 [[tab view] removeFromSuperview]; |
| 197 [[tab webController] setNativeProvider:nil]; |
| 198 } |
| 175 self.active = NO; | 199 self.active = NO; |
| 176 _webViewProxy.reset(); | 200 _webViewProxy.reset(); |
| 177 } | 201 } |
| 178 | 202 |
| 179 - (void)cancelLoad { | 203 - (void)cancelLoad { |
| 180 [self disconnectTab]; | 204 [self disconnectTab]; |
| 181 _loadInProgress = NO; | 205 _loadInProgress = NO; |
| 182 _loaded = NO; | 206 _loaded = NO; |
| 183 [_tab close]; | 207 _webState.reset(); |
| 184 _tab.reset(); | |
| 185 } | 208 } |
| 186 | 209 |
| 187 - (void)loadPendingSearchIfPossible { | 210 - (void)loadPendingSearchIfPossible { |
| 188 // If the search tab hasn't been created, or if it's already loaded, no-op. | 211 // 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) | 212 if (!_webState || _loadInProgress || self.active || _visibility == OFFSCREEN) |
| 190 return; | 213 return; |
| 191 | 214 |
| 192 // If this view is in a position where loading would be "preloading", check | 215 // If this view is in a position where loading would be "preloading", check |
| 193 // if that's allowed. | 216 // if that's allowed. |
| 194 if (_visibility == PRELOAD && | 217 if (_visibility == PRELOAD && |
| 195 !([_preloadChecker canPreloadSearchResults] && _preloadEnabled)) { | 218 !([_preloadChecker canPreloadSearchResults] && _preloadEnabled)) { |
| 196 return; | 219 return; |
| 197 } | 220 } |
| 198 [self loadTab]; | 221 [self loadTab]; |
| 199 } | 222 } |
| 200 | 223 |
| 201 - (void)loadTab { | 224 - (void)loadTab { |
| 202 DCHECK(_tab.get()); | 225 DCHECK(_webState); |
| 203 // Start observing the search tab. | 226 // Start observing the search tab. |
| 204 self.active = YES; | 227 self.active = YES; |
| 205 // TODO(crbug.com/546223): See if |_waitingForInitialSearchTabLoad| and | 228 // TODO(crbug.com/546223): See if |_waitingForInitialSearchTabLoad| and |
| 206 // |_loadInProgress| can be consolidated. | 229 // |_loadInProgress| can be consolidated. |
| 207 _waitingForInitialSearchTabLoad = YES; | 230 _waitingForInitialSearchTabLoad = YES; |
| 208 // Mark the start of the time for the search. | 231 // Mark the start of the time for the search. |
| 209 _loadStartTime = base::Time::Now(); | 232 _loadStartTime = base::Time::Now(); |
| 210 // Start the load by asking for the tab's view, but making it hidden. | 233 // Start the load by asking for the tab's view, but making it hidden. |
| 211 [_tab view].hidden = YES; | 234 Tab* tab = LegacyTabHelper::GetTabForWebState(_webState.get()); |
| 212 [self addSubview:[_tab view]]; | 235 [tab view].hidden = YES; |
| 236 [self addSubview:[tab view]]; |
| 213 _loadInProgress = YES; | 237 _loadInProgress = YES; |
| 214 } | 238 } |
| 215 | 239 |
| 216 - (void)displayTab { | 240 - (void)displayTab { |
| 217 [_tab view].frame = self.bounds; | 241 DCHECK(_webState); |
| 242 Tab* tab = LegacyTabHelper::GetTabForWebState(_webState.get()); |
| 243 [tab view].frame = self.bounds; |
| 218 _loadInProgress = NO; | 244 _loadInProgress = NO; |
| 219 | 245 |
| 220 void (^insertTab)(void) = ^{ | 246 void (^insertTab)(void) = ^{ |
| 221 [_tab view].hidden = NO; | 247 [tab view].hidden = NO; |
| 222 self.scrollEnabled = _shouldScroll; | 248 self.scrollEnabled = _shouldScroll; |
| 223 }; | 249 }; |
| 224 | 250 |
| 225 if (_visibility == VISIBLE) { | 251 if (_visibility == VISIBLE) { |
| 226 // Fade it in quickly. | 252 // Fade it in quickly. |
| 227 UIViewAnimationOptions options = | 253 UIViewAnimationOptions options = |
| 228 UIViewAnimationOptionTransitionCrossDissolve; | 254 UIViewAnimationOptionTransitionCrossDissolve; |
| 229 [UIView cr_transitionWithView:self | 255 [UIView cr_transitionWithView:self |
| 230 duration:ios::material::kDuration2 | 256 duration:ios::material::kDuration2 |
| 231 curve:ios::material::CurveEaseInOut | 257 curve:ios::material::CurveEaseInOut |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 withError:error | 380 withError:error |
| 355 isPost:isPost]; | 381 isPost:isPost]; |
| 356 | 382 |
| 357 if ([errorController respondsToSelector:@selector(setScrollEnabled:)]) { | 383 if ([errorController respondsToSelector:@selector(setScrollEnabled:)]) { |
| 358 [errorController setScrollEnabled:NO]; | 384 [errorController setScrollEnabled:NO]; |
| 359 } | 385 } |
| 360 return errorController; | 386 return errorController; |
| 361 } | 387 } |
| 362 | 388 |
| 363 @end | 389 @end |
| OLD | NEW |