Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/find_in_page/find_in_page_controller.h" | 5 #import "ios/chrome/browser/find_in_page/find_in_page_controller.h" |
| 6 | 6 |
| 7 #import <UIKit/UIKit.h> | 7 #import <UIKit/UIKit.h> |
| 8 | 8 |
| 9 #import <cmath> | 9 #import <cmath> |
| 10 #include <memory> | 10 #include <memory> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/mac/foundation_util.h" | 13 #include "base/mac/foundation_util.h" |
| 14 #include "base/mac/scoped_nsobject.h" | |
| 15 #import "ios/chrome/browser/find_in_page/find_in_page_model.h" | 14 #import "ios/chrome/browser/find_in_page/find_in_page_model.h" |
| 16 #import "ios/chrome/browser/find_in_page/js_findinpage_manager.h" | 15 #import "ios/chrome/browser/find_in_page/js_findinpage_manager.h" |
| 17 #import "ios/chrome/browser/web/dom_altering_lock.h" | 16 #import "ios/chrome/browser/web/dom_altering_lock.h" |
| 18 #import "ios/web/public/web_state/crw_web_view_proxy.h" | 17 #import "ios/web/public/web_state/crw_web_view_proxy.h" |
| 19 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" | 18 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" |
| 20 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" | 19 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" |
| 21 #import "ios/web/public/web_state/web_state.h" | 20 #import "ios/web/public/web_state/web_state.h" |
| 22 #import "ios/web/public/web_state/web_state_observer_bridge.h" | 21 #import "ios/web/public/web_state/web_state_observer_bridge.h" |
| 23 | 22 |
| 23 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 24 #error "This file requires ARC support." | |
| 25 #endif | |
| 26 | |
| 24 NSString* const kFindBarTextFieldWillBecomeFirstResponderNotification = | 27 NSString* const kFindBarTextFieldWillBecomeFirstResponderNotification = |
| 25 @"kFindBarTextFieldWillBecomeFirstResponderNotification"; | 28 @"kFindBarTextFieldWillBecomeFirstResponderNotification"; |
| 26 NSString* const kFindBarTextFieldDidResignFirstResponderNotification = | 29 NSString* const kFindBarTextFieldDidResignFirstResponderNotification = |
| 27 @"kFindBarTextFieldDidResignFirstResponderNotification"; | 30 @"kFindBarTextFieldDidResignFirstResponderNotification"; |
| 28 | 31 |
| 29 namespace { | 32 namespace { |
| 30 // The delay (in secs) after which the find in page string will be pumped again. | 33 // The delay (in secs) after which the find in page string will be pumped again. |
| 31 const NSTimeInterval kRecurringPumpDelay = .01; | 34 const NSTimeInterval kRecurringPumpDelay = .01; |
| 32 | 35 |
| 33 // Keeps find in page search term to be shared between different tabs. Never | 36 // Keeps find in page search term to be shared between different tabs. Never |
| 34 // reset, not stored on disk. | 37 // reset, not stored on disk. |
| 35 static NSString* gSearchTerm; | 38 static NSString* gSearchTerm; |
| 36 } | 39 } |
| 37 | 40 |
| 38 @interface FindInPageController () <DOMAltering, CRWWebStateObserver> | 41 @interface FindInPageController () <DOMAltering, CRWWebStateObserver> |
| 39 // The find in page controller delegate. | 42 // The find in page controller delegate. |
| 40 @property(nonatomic, readonly) id<FindInPageControllerDelegate> delegate; | 43 @property(nonatomic, readonly) id<FindInPageControllerDelegate> delegate; |
| 41 // The web view's scroll view. | 44 // The web view's scroll view. |
| 42 @property(nonatomic, readonly) CRWWebViewScrollViewProxy* webViewScrollView; | 45 @property(weak, nonatomic, readonly) |
|
noyau (Ping after 24h)
2016/11/25 12:56:26
This one also, readonly and weak makes no sense.
stkhapugin
2016/11/25 14:19:39
Same reason hundreds of our properties are readonl
| |
| 46 CRWWebViewScrollViewProxy* webViewScrollView; | |
| 43 | 47 |
| 44 // Find in Page text field listeners. | 48 // Find in Page text field listeners. |
| 45 - (void)findBarTextFieldWillBecomeFirstResponder:(NSNotification*)note; | 49 - (void)findBarTextFieldWillBecomeFirstResponder:(NSNotification*)note; |
| 46 - (void)findBarTextFieldDidResignFirstResponder:(NSNotification*)note; | 50 - (void)findBarTextFieldDidResignFirstResponder:(NSNotification*)note; |
| 47 // Keyboard listeners. | 51 // Keyboard listeners. |
| 48 - (void)keyboardDidShow:(NSNotification*)note; | 52 - (void)keyboardDidShow:(NSNotification*)note; |
| 49 - (void)keyboardWillHide:(NSNotification*)note; | 53 - (void)keyboardWillHide:(NSNotification*)note; |
| 50 // Constantly injects the find string in page until | 54 // Constantly injects the find string in page until |
| 51 // |disableFindInPageWithCompletionHandler:| is called or the find operation is | 55 // |disableFindInPageWithCompletionHandler:| is called or the find operation is |
| 52 // complete. Calls |completionHandler| if the find operation is complete. | 56 // complete. Calls |completionHandler| if the find operation is complete. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 69 - (web::WebState*)webState; | 73 - (web::WebState*)webState; |
| 70 @end | 74 @end |
| 71 | 75 |
| 72 @implementation FindInPageController { | 76 @implementation FindInPageController { |
| 73 @private | 77 @private |
| 74 // Object that manages find_in_page.js injection into the web view. | 78 // Object that manages find_in_page.js injection into the web view. |
| 75 __unsafe_unretained JsFindinpageManager* _findInPageJsManager; | 79 __unsafe_unretained JsFindinpageManager* _findInPageJsManager; |
| 76 __unsafe_unretained id<FindInPageControllerDelegate> _delegate; | 80 __unsafe_unretained id<FindInPageControllerDelegate> _delegate; |
| 77 | 81 |
| 78 // Access to the web view from the web state. | 82 // Access to the web view from the web state. |
| 79 base::scoped_nsprotocol<id<CRWWebViewProxy>> _webViewProxy; | 83 id<CRWWebViewProxy> _webViewProxy; |
| 80 | 84 |
| 81 // True when a find is in progress. Used to avoid running JavaScript during | 85 // True when a find is in progress. Used to avoid running JavaScript during |
| 82 // disable when there is nothing to clear. | 86 // disable when there is nothing to clear. |
| 83 BOOL _findStringStarted; | 87 BOOL _findStringStarted; |
| 84 | 88 |
| 85 // Bridge to observe the web state from Objective-C. | 89 // Bridge to observe the web state from Objective-C. |
| 86 std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge; | 90 std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge; |
| 87 } | 91 } |
| 88 | 92 |
| 89 @synthesize delegate = _delegate; | 93 @synthesize delegate = _delegate; |
| 90 | 94 |
| 91 + (void)setSearchTerm:(NSString*)string { | 95 + (void)setSearchTerm:(NSString*)string { |
| 92 [gSearchTerm release]; | |
| 93 gSearchTerm = [string copy]; | 96 gSearchTerm = [string copy]; |
| 94 } | 97 } |
| 95 | 98 |
| 96 + (NSString*)searchTerm { | 99 + (NSString*)searchTerm { |
| 97 return gSearchTerm; | 100 return gSearchTerm; |
| 98 } | 101 } |
| 99 | 102 |
| 100 - (id)initWithWebState:(web::WebState*)webState | 103 - (id)initWithWebState:(web::WebState*)webState |
| 101 delegate:(id<FindInPageControllerDelegate>)delegate { | 104 delegate:(id<FindInPageControllerDelegate>)delegate { |
| 102 self = [super init]; | 105 self = [super init]; |
| 103 if (self) { | 106 if (self) { |
| 104 DCHECK(delegate); | 107 DCHECK(delegate); |
| 105 _findInPageJsManager = base::mac::ObjCCastStrict<JsFindinpageManager>( | 108 _findInPageJsManager = base::mac::ObjCCastStrict<JsFindinpageManager>( |
| 106 [webState->GetJSInjectionReceiver() | 109 [webState->GetJSInjectionReceiver() |
| 107 instanceOfClass:[JsFindinpageManager class]]); | 110 instanceOfClass:[JsFindinpageManager class]]); |
| 108 _delegate = delegate; | 111 _delegate = delegate; |
| 109 _webStateObserverBridge.reset( | 112 _webStateObserverBridge.reset( |
| 110 new web::WebStateObserverBridge(webState, self)); | 113 new web::WebStateObserverBridge(webState, self)); |
| 111 _webViewProxy.reset([webState->GetWebViewProxy() retain]); | 114 _webViewProxy = webState->GetWebViewProxy(); |
| 112 [[NSNotificationCenter defaultCenter] | 115 [[NSNotificationCenter defaultCenter] |
| 113 addObserver:self | 116 addObserver:self |
| 114 selector:@selector(findBarTextFieldWillBecomeFirstResponder:) | 117 selector:@selector(findBarTextFieldWillBecomeFirstResponder:) |
| 115 name:kFindBarTextFieldWillBecomeFirstResponderNotification | 118 name:kFindBarTextFieldWillBecomeFirstResponderNotification |
| 116 object:nil]; | 119 object:nil]; |
| 117 [[NSNotificationCenter defaultCenter] | 120 [[NSNotificationCenter defaultCenter] |
| 118 addObserver:self | 121 addObserver:self |
| 119 selector:@selector(findBarTextFieldDidResignFirstResponder:) | 122 selector:@selector(findBarTextFieldDidResignFirstResponder:) |
| 120 name:kFindBarTextFieldDidResignFirstResponderNotification | 123 name:kFindBarTextFieldDidResignFirstResponderNotification |
| 121 object:nil]; | 124 object:nil]; |
| 122 DOMAlteringLock::CreateForWebState(webState); | 125 DOMAlteringLock::CreateForWebState(webState); |
| 123 } | 126 } |
| 124 return self; | 127 return self; |
| 125 } | 128 } |
| 126 | 129 |
| 127 - (void)dealloc { | 130 - (void)dealloc { |
| 128 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 131 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 129 [super dealloc]; | |
| 130 } | 132 } |
| 131 | 133 |
| 132 - (FindInPageModel*)findInPageModel { | 134 - (FindInPageModel*)findInPageModel { |
| 133 return [_findInPageJsManager findInPageModel]; | 135 return [_findInPageJsManager findInPageModel]; |
| 134 } | 136 } |
| 135 | 137 |
| 136 - (BOOL)canFindInPage { | 138 - (BOOL)canFindInPage { |
| 137 return [_webViewProxy hasSearchableTextContent]; | 139 return [_webViewProxy hasSearchableTextContent]; |
| 138 } | 140 } |
| 139 | 141 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 completionHandler(); | 187 completionHandler(); |
| 186 } | 188 } |
| 187 return; | 189 return; |
| 188 } | 190 } |
| 189 // Cancel any previous pumping. | 191 // Cancel any previous pumping. |
| 190 [NSObject cancelPreviousPerformRequestsWithTarget:self]; | 192 [NSObject cancelPreviousPerformRequestsWithTarget:self]; |
| 191 [self initFindInPage]; | 193 [self initFindInPage]; |
| 192 // Keep track of whether a find is in progress so to avoid running | 194 // Keep track of whether a find is in progress so to avoid running |
| 193 // JavaScript during disable if unnecessary. | 195 // JavaScript during disable if unnecessary. |
| 194 _findStringStarted = YES; | 196 _findStringStarted = YES; |
| 195 base::WeakNSObject<FindInPageController> weakSelf(self); | 197 __weak FindInPageController* weakSelf = self; |
| 196 [_findInPageJsManager findString:query | 198 [_findInPageJsManager findString:query |
| 197 completionHandler:^(BOOL finished, CGPoint point) { | 199 completionHandler:^(BOOL finished, CGPoint point) { |
| 198 [weakSelf processPumpResult:finished | 200 [weakSelf processPumpResult:finished |
| 199 scrollPoint:point | 201 scrollPoint:point |
| 200 completionHandler:completionHandler]; | 202 completionHandler:completionHandler]; |
| 201 }]; | 203 }]; |
| 202 }; | 204 }; |
| 203 DOMAlteringLock::FromWebState([self webState])->Acquire(self, lockAction); | 205 DOMAlteringLock::FromWebState([self webState])->Acquire(self, lockAction); |
| 204 } | 206 } |
| 205 | 207 |
| 206 - (void)startPumpingWithCompletionHandler:(ProceduralBlock)completionHandler { | 208 - (void)startPumpingWithCompletionHandler:(ProceduralBlock)completionHandler { |
| 207 base::WeakNSObject<FindInPageController> weakSelf(self); | 209 __weak FindInPageController* weakSelf = self; |
| 208 id completionHandlerBlock = ^void(BOOL findFinished) { | 210 id completionHandlerBlock = ^void(BOOL findFinished) { |
| 209 if (findFinished) { | 211 if (findFinished) { |
| 210 // Pumping complete. Nothing else to do. | 212 // Pumping complete. Nothing else to do. |
| 211 if (completionHandler) | 213 if (completionHandler) |
| 212 completionHandler(); | 214 completionHandler(); |
| 213 return; | 215 return; |
| 214 } | 216 } |
| 215 // Further pumping is required. | 217 // Further pumping is required. |
| 216 [weakSelf performSelector:@selector(startPumpingWithCompletionHandler:) | 218 [weakSelf performSelector:@selector(startPumpingWithCompletionHandler:) |
| 217 withObject:completionHandler | 219 withObject:completionHandler |
| 218 afterDelay:kRecurringPumpDelay]; | 220 afterDelay:kRecurringPumpDelay]; |
| 219 }; | 221 }; |
| 220 [self pumpFindStringInPageWithCompletionHandler:completionHandlerBlock]; | 222 [self pumpFindStringInPageWithCompletionHandler:completionHandlerBlock]; |
| 221 } | 223 } |
| 222 | 224 |
| 223 - (void)pumpFindStringInPageWithCompletionHandler: | 225 - (void)pumpFindStringInPageWithCompletionHandler: |
| 224 (void (^)(BOOL))completionHandler { | 226 (void (^)(BOOL))completionHandler { |
| 225 base::WeakNSObject<FindInPageController> weakSelf(self); | 227 __weak FindInPageController* weakSelf = self; |
| 226 [_findInPageJsManager pumpWithCompletionHandler:^(BOOL finished, | 228 [_findInPageJsManager pumpWithCompletionHandler:^(BOOL finished, |
| 227 CGPoint point) { | 229 CGPoint point) { |
| 228 base::scoped_nsobject<FindInPageController> strongSelf([weakSelf retain]); | 230 FindInPageController* strongSelf = weakSelf; |
| 229 if (finished) { | 231 if (finished) { |
| 230 [[strongSelf delegate] willAdjustScrollPosition]; | 232 [[strongSelf delegate] willAdjustScrollPosition]; |
| 231 point = [strongSelf limitOverscroll:[strongSelf webViewScrollView] | 233 point = [strongSelf limitOverscroll:[strongSelf webViewScrollView] |
| 232 atPoint:point]; | 234 atPoint:point]; |
| 233 [[strongSelf webViewScrollView] setContentOffset:point animated:YES]; | 235 [[strongSelf webViewScrollView] setContentOffset:point animated:YES]; |
| 234 } | 236 } |
| 235 completionHandler(finished); | 237 completionHandler(finished); |
| 236 }]; | 238 }]; |
| 237 } | 239 } |
| 238 | 240 |
| 239 - (void)findNextStringInPageWithCompletionHandler: | 241 - (void)findNextStringInPageWithCompletionHandler: |
| 240 (ProceduralBlock)completionHandler { | 242 (ProceduralBlock)completionHandler { |
| 241 [self initFindInPage]; | 243 [self initFindInPage]; |
| 242 base::WeakNSObject<FindInPageController> weakSelf(self); | 244 __weak FindInPageController* weakSelf = self; |
| 243 [_findInPageJsManager nextMatchWithCompletionHandler:^(CGPoint point) { | 245 [_findInPageJsManager nextMatchWithCompletionHandler:^(CGPoint point) { |
| 244 base::scoped_nsobject<FindInPageController> strongSelf([weakSelf retain]); | 246 FindInPageController* strongSelf = weakSelf; |
| 245 [[strongSelf delegate] willAdjustScrollPosition]; | 247 [[strongSelf delegate] willAdjustScrollPosition]; |
| 246 point = [strongSelf limitOverscroll:[strongSelf webViewScrollView] | 248 point = [strongSelf limitOverscroll:[strongSelf webViewScrollView] |
| 247 atPoint:point]; | 249 atPoint:point]; |
| 248 [[strongSelf webViewScrollView] setContentOffset:point animated:YES]; | 250 [[strongSelf webViewScrollView] setContentOffset:point animated:YES]; |
| 249 if (completionHandler) | 251 if (completionHandler) |
| 250 completionHandler(); | 252 completionHandler(); |
| 251 }]; | 253 }]; |
| 252 } | 254 } |
| 253 | 255 |
| 254 // Highlight the previous search match, update model and scroll to match. | 256 // Highlight the previous search match, update model and scroll to match. |
| 255 - (void)findPreviousStringInPageWithCompletionHandler: | 257 - (void)findPreviousStringInPageWithCompletionHandler: |
| 256 (ProceduralBlock)completionHandler { | 258 (ProceduralBlock)completionHandler { |
| 257 [self initFindInPage]; | 259 [self initFindInPage]; |
| 258 base::WeakNSObject<FindInPageController> weakSelf(self); | 260 __weak FindInPageController* weakSelf = self; |
| 259 [_findInPageJsManager previousMatchWithCompletionHandler:^(CGPoint point) { | 261 [_findInPageJsManager previousMatchWithCompletionHandler:^(CGPoint point) { |
| 260 base::scoped_nsobject<FindInPageController> strongSelf([weakSelf retain]); | 262 FindInPageController* strongSelf = weakSelf; |
| 261 [[strongSelf delegate] willAdjustScrollPosition]; | 263 [[strongSelf delegate] willAdjustScrollPosition]; |
| 262 point = [strongSelf limitOverscroll:[strongSelf webViewScrollView] | 264 point = [strongSelf limitOverscroll:[strongSelf webViewScrollView] |
| 263 atPoint:point]; | 265 atPoint:point]; |
| 264 [[strongSelf webViewScrollView] setContentOffset:point animated:YES]; | 266 [[strongSelf webViewScrollView] setContentOffset:point animated:YES]; |
| 265 if (completionHandler) | 267 if (completionHandler) |
| 266 completionHandler(); | 268 completionHandler(); |
| 267 }]; | 269 }]; |
| 268 } | 270 } |
| 269 | 271 |
| 270 // Remove highlights from the page and disable the model. | 272 // Remove highlights from the page and disable the model. |
| 271 - (void)disableFindInPageWithCompletionHandler: | 273 - (void)disableFindInPageWithCompletionHandler: |
| 272 (ProceduralBlock)completionHandler { | 274 (ProceduralBlock)completionHandler { |
| 273 if (![self canFindInPage]) | 275 if (![self canFindInPage]) |
| 274 return; | 276 return; |
| 275 // Cancel any queued calls to |recurringPumpWithCompletionHandler|. | 277 // Cancel any queued calls to |recurringPumpWithCompletionHandler|. |
| 276 [NSObject cancelPreviousPerformRequestsWithTarget:self]; | 278 [NSObject cancelPreviousPerformRequestsWithTarget:self]; |
| 277 base::WeakNSObject<FindInPageController> weakSelf(self); | 279 __weak FindInPageController* weakSelf = self; |
| 278 ProceduralBlock handler = ^{ | 280 ProceduralBlock handler = ^{ |
| 279 base::scoped_nsobject<FindInPageController> strongSelf([weakSelf retain]); | 281 FindInPageController* strongSelf = weakSelf; |
| 280 if (strongSelf) { | 282 if (strongSelf) { |
| 281 [strongSelf.get().findInPageModel setEnabled:NO]; | 283 [strongSelf.findInPageModel setEnabled:NO]; |
| 282 web::WebState* webState = [strongSelf webState]; | 284 web::WebState* webState = [strongSelf webState]; |
| 283 if (webState) | 285 if (webState) |
| 284 DOMAlteringLock::FromWebState(webState)->Release(strongSelf); | 286 DOMAlteringLock::FromWebState(webState)->Release(strongSelf); |
| 285 } | 287 } |
| 286 if (completionHandler) | 288 if (completionHandler) |
| 287 completionHandler(); | 289 completionHandler(); |
| 288 }; | 290 }; |
| 289 // Only run JSFindInPageManager disable if there is a string in progress to | 291 // Only run JSFindInPageManager disable if there is a string in progress to |
| 290 // avoid WKWebView crash on deallocation due to outstanding completion | 292 // avoid WKWebView crash on deallocation due to outstanding completion |
| 291 // handler. | 293 // handler. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 | 376 |
| 375 - (BOOL)canReleaseDOMLock { | 377 - (BOOL)canReleaseDOMLock { |
| 376 return NO; | 378 return NO; |
| 377 } | 379 } |
| 378 | 380 |
| 379 - (void)releaseDOMLockWithCompletionHandler:(ProceduralBlock)completionHandler { | 381 - (void)releaseDOMLockWithCompletionHandler:(ProceduralBlock)completionHandler { |
| 380 NOTREACHED(); | 382 NOTREACHED(); |
| 381 } | 383 } |
| 382 | 384 |
| 383 @end | 385 @end |
| OLD | NEW |