Commit 5f978ae9 authored by Chris Lu's avatar Chris Lu Committed by Commit Bot

[ios] Implement FindInPageManagerDelegate

Add delegate for FindInPageManager. CreateFindInpageManagerTest to
test it's behavior. Add property inFindInPageManagerImpl to keep track
of total matches in a find.

Bug: 896867
Change-Id: I0c4b951c898eb8f3f91562a564db369b66afa78e
Reviewed-on: https://chromium-review.googlesource.com/c/1436946
Commit-Queue: Chris Lu <thegreenfrog@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Reviewed-by: default avatarMike Dougherty <michaeldo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#628437}
parent de593b83
......@@ -29,6 +29,8 @@ class FindInPageManagerImpl : public FindInPageManager,
// FindInPageManager overrides
void Find(NSString* query, FindInPageOptions options) override;
void StopFinding() override;
FindInPageManagerDelegate* GetDelegate() override;
void SetDelegate(FindInPageManagerDelegate* delegate) override;
private:
friend class web::WebStateUserData<FindInPageManagerImpl>;
......@@ -36,6 +38,7 @@ class FindInPageManagerImpl : public FindInPageManager,
struct FindRequest {
FindRequest();
~FindRequest();
int GetTotalMatchCount() const;
// Unique identifier for each find used to check that it is the most recent
// find. This ensures that an old find doesn't decrement
// |pending_frame_calls_count| after it has been reset by the new find.
......@@ -65,6 +68,7 @@ class FindInPageManagerImpl : public FindInPageManager,
// Holds the state of the most recent find in page request.
FindRequest last_find_request_;
FindInPageManagerDelegate* delegate_ = nullptr;
web::WebState* web_state_ = nullptr;
base::WeakPtrFactory<FindInPageManagerImpl> weak_factory_;
};
......
......@@ -7,6 +7,7 @@
#import "base/strings/sys_string_conversions.h"
#include "base/values.h"
#import "ios/web/find_in_page/find_in_page_constants.h"
#import "ios/web/public/find_in_page/find_in_page_manager_delegate.h"
#import "ios/web/public/web_state/web_frame.h"
#include "ios/web/public/web_state/web_frame_util.h"
#import "ios/web/public/web_state/web_frames_manager.h"
......@@ -51,10 +52,25 @@ FindInPageManagerImpl::~FindInPageManagerImpl() {
}
}
FindInPageManagerDelegate* FindInPageManagerImpl::GetDelegate() {
return delegate_;
}
void FindInPageManagerImpl::SetDelegate(FindInPageManagerDelegate* delegate) {
delegate_ = delegate;
}
FindInPageManagerImpl::FindRequest::FindRequest() {}
FindInPageManagerImpl::FindRequest::~FindRequest() {}
int FindInPageManagerImpl::FindRequest::GetTotalMatchCount() const {
int matches = 0;
for (auto pair : frame_match_count) {
matches += pair.second;
}
return matches;
}
void FindInPageManagerImpl::WebFrameDidBecomeAvailable(WebState* web_state,
WebFrame* web_frame) {
const std::string frame_id = web_frame->GetFrameId();
......@@ -118,35 +134,45 @@ void FindInPageManagerImpl::ProcessFindInPageResult(const std::string& query,
// New find was started.
return;
}
if (!web_state_) {
// WebState was destroyed before find finished.
return;
}
last_find_request_.pending_frame_call_count--;
WebFrame* frame = GetWebFrameWithId(web_state_, frame_id);
// The frame no longer exists. If frame is removed during find, result will
// be null.
if (!result || !frame) {
return;
}
// The frame no longer exists or the function call timed out. In both cases,
// result will be null.
// Zero out count to ensure every frame is updated for every find.
last_find_request_.frame_match_count[frame_id] = 0;
} else {
int match_count = 0;
if (result->is_double()) {
// Valid match number returned. If not, match count will be 0 in order to
// zero-out count from previous find.
match_count = static_cast<int>(result->GetDouble());
}
// If response is equal to kFindInPagePending, find did not finish in the
// JavaScript. Call pumpSearch to continue find.
if (match_count == kFindInPagePending) {
std::vector<base::Value> params;
params.push_back(base::Value(kFindInPageFindTimeout));
frame->CallJavaScriptFunction(
kFindInPagePump, params,
base::BindOnce(&FindInPageManagerImpl::ProcessFindInPageResult,
weak_factory_.GetWeakPtr(), query, frame_id,
unique_id),
base::TimeDelta::FromSeconds(kJavaScriptFunctionCallTimeout));
return;
}
int matches_count = 0;
if (result->is_double()) {
// Valid match number returned. If not, match count will be 0 in order to
// zero-out count from previous find.
matches_count = static_cast<int>(result->GetDouble());
last_find_request_.frame_match_count[frame_id] = match_count;
}
// If response is equal to kFindInPagePending, find did not finish in the
// JavaScript. Call pumpSearch to continue find.
if (matches_count == kFindInPagePending) {
std::vector<base::Value> params;
params.push_back(base::Value(kFindInPageFindTimeout));
frame->CallJavaScriptFunction(
kFindInPagePump, params,
base::BindOnce(&FindInPageManagerImpl::ProcessFindInPageResult,
weak_factory_.GetWeakPtr(), query, frame_id, unique_id),
base::TimeDelta::FromSeconds(kJavaScriptFunctionCallTimeout));
return;
if (last_find_request_.pending_frame_call_count == 0) {
int total_match_count = last_find_request_.GetTotalMatchCount();
delegate_->DidCountMatches(web_state_, total_match_count, query);
}
last_find_request_.frame_match_count[frame_id] = matches_count;
}
} // namespace web
......@@ -10,6 +10,7 @@ source_set("find_in_page") {
sources = [
"find_in_page_manager.h",
"find_in_page_manager_delegate.h",
]
configs += [ "//build/config/compiler:enable_arc" ]
......
......@@ -12,6 +12,8 @@
namespace web {
class FindInPageManagerDelegate;
// Indicates what action the FindinPageManager should take.
enum class FindInPageOptions {
// Search for a string. Highlight and scroll to the first result if
......@@ -35,12 +37,21 @@ class FindInPageManager : public web::WebStateUserData<FindInPageManager> {
// on |options|. |query| must not be null if |options| is |FindInPageSearch|.
// |query| is ignored if |options| is not |FindInPageSearch|. If new search is
// started before previous search finishes, old request will be discarded.
//
// FindInPageManagerDelegate::DidCountMatches() will be called to return the
// total matches found if FindInPageSearch is passed, assuming it hasn't been
// discarded. FindInPageManagerDelegate::DidHighlightMatch() will also be
// called if matches were found to inform client of the new match that was
// highlighted for all FindInPageOptions.
virtual void Find(NSString* query, FindInPageOptions options) = 0;
// Removes any highlighting. Does nothing if Find() with
// FindInPageOptions::FindInPageSearch is never called.
virtual void StopFinding() = 0;
virtual FindInPageManagerDelegate* GetDelegate() = 0;
virtual void SetDelegate(FindInPageManagerDelegate* delegate) = 0;
~FindInPageManager() override {}
protected:
......
// 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_WEB_PUBLIC_FIND_IN_PAGE_FIND_IN_PAGE_MANAGER_DELEGATE_H_
#define IOS_WEB_PUBLIC_FIND_IN_PAGE_FIND_IN_PAGE_MANAGER_DELEGATE_H_
#include <string>
namespace web {
class WebState;
class FindInPageManagerDelegate {
public:
FindInPageManagerDelegate() = default;
// Called when a search for |query| finished with |match_count| found after
// calling FindInPageManager::Find() with FindInPageSearch. Even if no matches
// are found, call will be made once a find has completed, assuming it has not
// been interrupted by another find. Client should check |query| to ensure
// that it is processing |match_count| for the correct find.
virtual void DidCountMatches(WebState* web_state,
int match_count,
const std::string& query) = 0;
// Called when a match number |index| is highlighted. This is triggered by
// calling FindInPageManager::Find() with any FindInPageOptions to indicate
// the new match number that was highlighted. This method is not called if
// |FindInPageManager::Find| did not find any matches.
virtual void DidHighlightMatch(WebState* web_state, int index) = 0;
protected:
virtual ~FindInPageManagerDelegate() = default;
private:
DISALLOW_COPY_AND_ASSIGN(FindInPageManagerDelegate);
};
} // namespace web
#endif // IOS_WEB_PUBLIC_FIND_IN_PAGE_FIND_IN_PAGE_MANAGER_DELEGATE_H_
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