Commit 53200406 authored by Chris Lu's avatar Chris Lu Committed by Commit Bot

[ios] Use FindInPageManager when feature flag is turned on.

Bug: 919685
Change-Id: I306637940553044ed6fd57b13f00c0d12b6cd0c3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1566612Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Reviewed-by: default avatarYi Su <mrsuyi@chromium.org>
Commit-Queue: Chris Lu <thegreenfrog@chromium.org>
Cr-Commit-Position: refs/heads/master@{#652295}
parent 83be1e44
...@@ -11,17 +11,21 @@ source_set("find_in_page") { ...@@ -11,17 +11,21 @@ source_set("find_in_page") {
"find_in_page_controller.mm", "find_in_page_controller.mm",
"find_in_page_model.h", "find_in_page_model.h",
"find_in_page_model.mm", "find_in_page_model.mm",
"find_in_page_response_delegate.h",
"find_tab_helper.h", "find_tab_helper.h",
"find_tab_helper.mm", "find_tab_helper.mm",
"js_findinpage_manager.h", "js_findinpage_manager.h",
"js_findinpage_manager.mm", "js_findinpage_manager.mm",
] ]
deps = [ deps = [
":feature_flags",
":injected_js", ":injected_js",
"//base", "//base",
"//ios/chrome/browser/metrics:ukm_url_recorder", "//ios/chrome/browser/metrics:ukm_url_recorder",
"//ios/chrome/browser/web", "//ios/chrome/browser/web",
"//ios/web", "//ios/web",
"//ios/web/public",
"//ios/web/public/find_in_page",
"//services/metrics/public/cpp:ukm_builders", "//services/metrics/public/cpp:ukm_builders",
] ]
libs = [ "CoreGraphics.framework" ] libs = [ "CoreGraphics.framework" ]
...@@ -61,6 +65,7 @@ source_set("unit_tests") { ...@@ -61,6 +65,7 @@ source_set("unit_tests") {
"//base/test:test_support", "//base/test:test_support",
"//components/ukm:test_support", "//components/ukm:test_support",
"//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/find_in_page:feature_flags",
"//ios/chrome/browser/metrics:ukm_url_recorder", "//ios/chrome/browser/metrics:ukm_url_recorder",
"//ios/chrome/browser/web:test_support", "//ios/chrome/browser/web:test_support",
"//ios/chrome/browser/web:web_internal", "//ios/chrome/browser/web:web_internal",
......
...@@ -14,6 +14,7 @@ class WebState; ...@@ -14,6 +14,7 @@ class WebState;
} }
@class FindInPageModel; @class FindInPageModel;
@protocol FindInPageResponseDelegate;
extern NSString* const kFindBarTextFieldWillBecomeFirstResponderNotification; extern NSString* const kFindBarTextFieldWillBecomeFirstResponderNotification;
extern NSString* const kFindBarTextFieldDidResignFirstResponderNotification; extern NSString* const kFindBarTextFieldDidResignFirstResponderNotification;
...@@ -22,6 +23,9 @@ extern NSString* const kFindBarTextFieldDidResignFirstResponderNotification; ...@@ -22,6 +23,9 @@ extern NSString* const kFindBarTextFieldDidResignFirstResponderNotification;
// Find In Page model. // Find In Page model.
@property(nonatomic, readonly, strong) FindInPageModel* findInPageModel; @property(nonatomic, readonly, strong) FindInPageModel* findInPageModel;
// FindInPageResponseDelegate instance used to pass back responses to find
// actions when kFindInPageiFrame is enabled.
@property(nonatomic, weak) id<FindInPageResponseDelegate> responseDelegate;
// Designated initializer. // Designated initializer.
- (id)initWithWebState:(web::WebState*)webState; - (id)initWithWebState:(web::WebState*)webState;
......
...@@ -11,10 +11,14 @@ ...@@ -11,10 +11,14 @@
#include "base/logging.h" #include "base/logging.h"
#import "base/mac/foundation_util.h" #import "base/mac/foundation_util.h"
#import "ios/chrome/browser/find_in_page/features.h"
#import "ios/chrome/browser/find_in_page/find_in_page_model.h" #import "ios/chrome/browser/find_in_page/find_in_page_model.h"
#import "ios/chrome/browser/find_in_page/find_in_page_response_delegate.h"
#import "ios/chrome/browser/find_in_page/js_findinpage_manager.h" #import "ios/chrome/browser/find_in_page/js_findinpage_manager.h"
#include "ios/chrome/browser/metrics/ukm_url_recorder.h" #include "ios/chrome/browser/metrics/ukm_url_recorder.h"
#import "ios/chrome/browser/web/dom_altering_lock.h" #import "ios/chrome/browser/web/dom_altering_lock.h"
#import "ios/web/public/find_in_page/find_in_page_manager.h"
#import "ios/web/public/find_in_page/find_in_page_manager_delegate_bridge.h"
#import "ios/web/public/web_state/js/crw_js_injection_receiver.h" #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
#import "ios/web/public/web_state/ui/crw_web_view_proxy.h" #import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" #import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
...@@ -40,7 +44,9 @@ const NSTimeInterval kRecurringPumpDelay = .01; ...@@ -40,7 +44,9 @@ const NSTimeInterval kRecurringPumpDelay = .01;
static NSString* gSearchTerm; static NSString* gSearchTerm;
} }
@interface FindInPageController () <DOMAltering, CRWWebStateObserver> @interface FindInPageController () <DOMAltering,
CRWWebStateObserver,
CRWFindInPageManagerDelegate>
// The web view's scroll view. // The web view's scroll view.
- (CRWWebViewScrollViewProxy*)webViewScrollView; - (CRWWebViewScrollViewProxy*)webViewScrollView;
...@@ -73,9 +79,14 @@ static NSString* gSearchTerm; ...@@ -73,9 +79,14 @@ static NSString* gSearchTerm;
@end @end
@implementation FindInPageController { @implementation FindInPageController {
// Object that manages find_in_page.js injection into the web view. // Object that manages find_in_page.js injection into the web view when
// kFindInPageiFrame flag is disabled.
__weak JsFindinpageManager* _findInPageJsManager; __weak JsFindinpageManager* _findInPageJsManager;
// Object that manages searches and match traversals when kFindInPageiFrame
// flag is enabled.
web::FindInPageManager* _findInPageManager;
// Access to the web view from the web state. // Access to the web view from the web state.
id<CRWWebViewProxy> _webViewProxy; id<CRWWebViewProxy> _webViewProxy;
...@@ -89,6 +100,10 @@ static NSString* gSearchTerm; ...@@ -89,6 +100,10 @@ static NSString* gSearchTerm;
// Bridge to observe the web state from Objective-C. // Bridge to observe the web state from Objective-C.
std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge; std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge;
// Bridge to observe FindInPageManager from Objective-C.
std::unique_ptr<web::FindInPageManagerDelegateBridge>
_findInPageDelegateBridge;
} }
@synthesize findInPageModel = _findInPageModel; @synthesize findInPageModel = _findInPageModel;
...@@ -107,10 +122,18 @@ static NSString* gSearchTerm; ...@@ -107,10 +122,18 @@ static NSString* gSearchTerm;
DCHECK(webState); DCHECK(webState);
_webState = webState; _webState = webState;
_findInPageModel = [[FindInPageModel alloc] init]; _findInPageModel = [[FindInPageModel alloc] init];
_findInPageJsManager = base::mac::ObjCCastStrict<JsFindinpageManager>( if (base::FeatureList::IsEnabled(kFindInPageiFrame)) {
[_webState->GetJSInjectionReceiver() _findInPageDelegateBridge =
instanceOfClass:[JsFindinpageManager class]]); std::make_unique<web::FindInPageManagerDelegateBridge>(self);
_findInPageJsManager.findInPageModel = _findInPageModel; _findInPageManager = web::FindInPageManager::FromWebState(_webState);
_findInPageManager->SetDelegate(_findInPageDelegateBridge.get());
} else {
_findInPageJsManager = base::mac::ObjCCastStrict<JsFindinpageManager>(
[_webState->GetJSInjectionReceiver()
instanceOfClass:[JsFindinpageManager class]]);
_findInPageJsManager.findInPageModel = _findInPageModel;
}
_webStateObserverBridge = _webStateObserverBridge =
std::make_unique<web::WebStateObserverBridge>(self); std::make_unique<web::WebStateObserverBridge>(self);
_webState->AddObserver(_webStateObserverBridge.get()); _webState->AddObserver(_webStateObserverBridge.get());
...@@ -201,22 +224,28 @@ static NSString* gSearchTerm; ...@@ -201,22 +224,28 @@ static NSString* gSearchTerm;
} }
// Cancel any previous pumping. // Cancel any previous pumping.
[NSObject cancelPreviousPerformRequestsWithTarget:self]; [NSObject cancelPreviousPerformRequestsWithTarget:self];
[self initFindInPage];
// Keep track of whether a find is in progress so to avoid running // Keep track of whether a find is in progress so to avoid running
// JavaScript during disable if unnecessary. // JavaScript during disable if unnecessary.
_findStringStarted = YES; _findStringStarted = YES;
__weak FindInPageController* weakSelf = self;
[_findInPageJsManager findString:query if (base::FeatureList::IsEnabled(kFindInPageiFrame)) {
completionHandler:^(BOOL finished, CGPoint point) { _findInPageManager->Find(query, web::FindInPageOptions::FindInPageSearch);
FindInPageController* strongSelf = weakSelf; } else {
if (!strongSelf) { [self initFindInPage];
return; __weak FindInPageController* weakSelf = self;
} [_findInPageJsManager findString:query
[strongSelf logFindInPageSearchUKM]; completionHandler:^(BOOL finished, CGPoint point) {
[strongSelf processPumpResult:finished FindInPageController* strongSelf = weakSelf;
scrollPoint:point if (!strongSelf) {
completionHandler:completionHandler]; return;
}]; }
[strongSelf logFindInPageSearchUKM];
[strongSelf processPumpResult:finished
scrollPoint:point
completionHandler:completionHandler];
}];
}
}; };
DOMAlteringLock::FromWebState(_webState)->Acquire(self, lockAction); DOMAlteringLock::FromWebState(_webState)->Acquire(self, lockAction);
} }
...@@ -255,31 +284,39 @@ static NSString* gSearchTerm; ...@@ -255,31 +284,39 @@ static NSString* gSearchTerm;
- (void)findNextStringInPageWithCompletionHandler: - (void)findNextStringInPageWithCompletionHandler:
(ProceduralBlock)completionHandler { (ProceduralBlock)completionHandler {
[self initFindInPage]; if (base::FeatureList::IsEnabled(kFindInPageiFrame)) {
__weak FindInPageController* weakSelf = self; _findInPageManager->Find(nil, web::FindInPageOptions::FindInPageNext);
[_findInPageJsManager nextMatchWithCompletionHandler:^(CGPoint point) { } else {
FindInPageController* strongSelf = weakSelf; [self initFindInPage];
point = [strongSelf limitOverscroll:[strongSelf webViewScrollView] __weak FindInPageController* weakSelf = self;
atPoint:point]; [_findInPageJsManager nextMatchWithCompletionHandler:^(CGPoint point) {
[[strongSelf webViewScrollView] setContentOffset:point animated:YES]; FindInPageController* strongSelf = weakSelf;
if (completionHandler) point = [strongSelf limitOverscroll:[strongSelf webViewScrollView]
completionHandler(); atPoint:point];
}]; [[strongSelf webViewScrollView] setContentOffset:point animated:YES];
if (completionHandler)
completionHandler();
}];
}
} }
// Highlight the previous search match, update model and scroll to match. // Highlight the previous search match, update model and scroll to match.
- (void)findPreviousStringInPageWithCompletionHandler: - (void)findPreviousStringInPageWithCompletionHandler:
(ProceduralBlock)completionHandler { (ProceduralBlock)completionHandler {
[self initFindInPage]; if (base::FeatureList::IsEnabled(kFindInPageiFrame)) {
__weak FindInPageController* weakSelf = self; _findInPageManager->Find(nil, web::FindInPageOptions::FindInPagePrevious);
[_findInPageJsManager previousMatchWithCompletionHandler:^(CGPoint point) { } else {
FindInPageController* strongSelf = weakSelf; [self initFindInPage];
point = [strongSelf limitOverscroll:[strongSelf webViewScrollView] __weak FindInPageController* weakSelf = self;
atPoint:point]; [_findInPageJsManager previousMatchWithCompletionHandler:^(CGPoint point) {
[[strongSelf webViewScrollView] setContentOffset:point animated:YES]; FindInPageController* strongSelf = weakSelf;
if (completionHandler) point = [strongSelf limitOverscroll:[strongSelf webViewScrollView]
completionHandler(); atPoint:point];
}]; [[strongSelf webViewScrollView] setContentOffset:point animated:YES];
if (completionHandler)
completionHandler();
}];
}
} }
// Remove highlights from the page and disable the model. // Remove highlights from the page and disable the model.
...@@ -327,6 +364,27 @@ static NSString* gSearchTerm; ...@@ -327,6 +364,27 @@ static NSString* gSearchTerm;
[[self findInPageModel] updateQuery:(term ? term : @"") matches:0]; [[self findInPageModel] updateQuery:(term ? term : @"") matches:0];
} }
#pragma mark - CRWFindInPageManagerDelegate
- (void)findInPageManager:(web::FindInPageManager*)manager
didHighlightMatchesOfQuery:(NSString*)query
withMatchCount:(NSInteger)matchCount
forWebState:(web::WebState*)webState {
[self.findInPageModel updateQuery:query matches:matchCount];
[self logFindInPageSearchUKM];
[self.responseDelegate findDidFinishWithUpdatedModel:self.findInPageModel];
}
- (void)findInPageManager:(web::FindInPageManager*)manager
didSelectMatchAtIndex:(NSInteger)index
forWebState:(web::WebState*)webState {
// Increment index so that match number show in FindBar ranges from 1...N as
// opposed to 0...N-1.
index++;
[self.findInPageModel updateIndex:index atPoint:CGPointZero];
[self.responseDelegate findDidFinishWithUpdatedModel:self.findInPageModel];
}
#pragma mark - Notification listeners #pragma mark - Notification listeners
- (void)findBarTextFieldWillBecomeFirstResponder:(NSNotification*)note { - (void)findBarTextFieldWillBecomeFirstResponder:(NSNotification*)note {
......
...@@ -59,6 +59,7 @@ TEST_F(FindInPageControllerTest, VerifyUKMLoggedTrue) { ...@@ -59,6 +59,7 @@ TEST_F(FindInPageControllerTest, VerifyUKMLoggedTrue) {
completion_handler_finished = true; completion_handler_finished = true;
}]; }];
ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
base::RunLoop().RunUntilIdle();
return completion_handler_finished; return completion_handler_finished;
})); }));
// Single true entry should be recorded for the interaction above. // Single true entry should be recorded for the interaction above.
...@@ -81,6 +82,7 @@ TEST_F(FindInPageControllerTest, VerifyUKMLoggedFalse) { ...@@ -81,6 +82,7 @@ TEST_F(FindInPageControllerTest, VerifyUKMLoggedFalse) {
completion_handler_finished = true; completion_handler_finished = true;
}]; }];
ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
base::RunLoop().RunUntilIdle();
return completion_handler_finished; return completion_handler_finished;
})); }));
// Single false entry should be recorded for the interaction above. // Single false entry should be recorded for the interaction above.
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_FIND_IN_PAGE_FIND_IN_PAGE_RESPONSE_DELEGATE_H_
#define IOS_CHROME_BROWSER_FIND_IN_PAGE_FIND_IN_PAGE_RESPONSE_DELEGATE_H_
@class FindInPageModel;
// Delegate class to relay responses of FindInPageController calls to
// BrowserViewController.
@protocol FindInPageResponseDelegate
@optional
// Called once a Find action finishes.
- (void)findDidFinishWithUpdatedModel:(FindInPageModel*)model;
@end
#endif // IOS_CHROME_BROWSER_FIND_IN_PAGE_FIND_IN_PAGE_RESPONSE_DELEGATE_H_
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
@class FindInPageController; @class FindInPageController;
@class FindInPageModel; @class FindInPageModel;
@protocol FindInPageResponseDelegate;
typedef void (^FindInPageCompletionBlock)(FindInPageModel*); typedef void (^FindInPageCompletionBlock)(FindInPageModel*);
...@@ -33,6 +34,10 @@ class FindTabHelper : public web::WebStateObserver, ...@@ -33,6 +34,10 @@ class FindTabHelper : public web::WebStateObserver,
REVERSE, REVERSE,
}; };
// Sets the FindInPageResponseDelegate delegate to send responses to
// StartFinding(), ContinueFinding(), and StopFinding().
void SetResponseDelegate(id<FindInPageResponseDelegate> response_delegate);
// Starts an asynchronous Find operation that will call the given completion // Starts an asynchronous Find operation that will call the given completion
// handler with results. Highlights matches on the current page. Always // handler with results. Highlights matches on the current page. Always
// searches in the FORWARD direction. // searches in the FORWARD direction.
......
...@@ -25,6 +25,11 @@ FindTabHelper::FindTabHelper(web::WebState* web_state) { ...@@ -25,6 +25,11 @@ FindTabHelper::FindTabHelper(web::WebState* web_state) {
FindTabHelper::~FindTabHelper() {} FindTabHelper::~FindTabHelper() {}
void FindTabHelper::SetResponseDelegate(
id<FindInPageResponseDelegate> response_delegate) {
controller_.responseDelegate = response_delegate;
}
void FindTabHelper::StartFinding(NSString* search_term, void FindTabHelper::StartFinding(NSString* search_term,
FindInPageCompletionBlock completion) { FindInPageCompletionBlock completion) {
base::RecordAction(base::UserMetricsAction(kFindActionName)); base::RecordAction(base::UserMetricsAction(kFindActionName));
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#import "ios/chrome/browser/download/download_manager_tab_helper.h" #import "ios/chrome/browser/download/download_manager_tab_helper.h"
#include "ios/chrome/browser/feature_engagement/tracker_factory.h" #include "ios/chrome/browser/feature_engagement/tracker_factory.h"
#include "ios/chrome/browser/feature_engagement/tracker_util.h" #include "ios/chrome/browser/feature_engagement/tracker_util.h"
#import "ios/chrome/browser/find_in_page/find_in_page_response_delegate.h"
#import "ios/chrome/browser/find_in_page/find_tab_helper.h" #import "ios/chrome/browser/find_in_page/find_tab_helper.h"
#include "ios/chrome/browser/first_run/first_run.h" #include "ios/chrome/browser/first_run/first_run.h"
#import "ios/chrome/browser/geolocation/omnibox_geolocation_controller.h" #import "ios/chrome/browser/geolocation/omnibox_geolocation_controller.h"
...@@ -372,6 +373,7 @@ NSString* const kBrowserViewControllerSnackbarCategory = ...@@ -372,6 +373,7 @@ NSString* const kBrowserViewControllerSnackbarCategory =
CRWWebStateDelegate, CRWWebStateDelegate,
CRWWebStateObserver, CRWWebStateObserver,
DialogPresenterDelegate, DialogPresenterDelegate,
FindInPageResponseDelegate,
FullscreenUIElement, FullscreenUIElement,
InfobarPositioner, InfobarPositioner,
KeyCommandsPlumbing, KeyCommandsPlumbing,
...@@ -4222,6 +4224,7 @@ NSString* const kBrowserViewControllerSnackbarCategory = ...@@ -4222,6 +4224,7 @@ NSString* const kBrowserViewControllerSnackbarCategory =
DCHECK(tab); DCHECK(tab);
auto* helper = FindTabHelper::FromWebState(tab.webState); auto* helper = FindTabHelper::FromWebState(tab.webState);
DCHECK(!helper->IsFindUIActive()); DCHECK(!helper->IsFindUIActive());
helper->SetResponseDelegate(self);
helper->SetFindUIActive(true); helper->SetFindUIActive(true);
[self showFindBarWithAnimation:YES selectText:YES shouldFocus:YES]; [self showFindBarWithAnimation:YES selectText:YES shouldFocus:YES];
} }
...@@ -4340,6 +4343,12 @@ NSString* const kBrowserViewControllerSnackbarCategory = ...@@ -4340,6 +4343,12 @@ NSString* const kBrowserViewControllerSnackbarCategory =
[self searchByResizedImageData:data atURL:nil inNewTab:NO]; [self searchByResizedImageData:data atURL:nil inNewTab:NO];
} }
#pragma mark - FindInPageResponseDelegate
- (void)findDidFinishWithUpdatedModel:(FindInPageModel*)model {
[_findBarController updateResultsCount:model];
}
#pragma mark - BrowserCommands helpers #pragma mark - BrowserCommands helpers
// Reloads the original url of the last non-redirect item (including non-history // Reloads the original url of the last non-redirect item (including non-history
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment