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