15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "android_webview/browser/find_helper.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/message_loop/message_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/stop_find_action.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "third_party/WebKit/public/web/WebFindOptions.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebFindOptions;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace android_webview {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FindHelper::FindHelper(WebContents* web_contents)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : WebContentsObserver(web_contents),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listener_(NULL),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      async_find_started_(false),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_find_started_(false),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      find_request_id_counter_(0),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_request_id_(0),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_match_count_(-1),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_active_ordinal_(-1),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_factory_(this) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FindHelper::~FindHelper() {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FindHelper::SetListener(Listener* listener) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener_ = listener;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FindHelper::FindAllAsync(const base::string16& search_string) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop any ongoing asynchronous request.
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents()->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_find_started_ = false;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  async_find_started_ = true;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebFindOptions options;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.forward = true;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.matchCase = false;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.findNext = false;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartNewRequest(search_string);
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents()->Find(current_request_id_, search_string, options);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FindHelper::HandleFindReply(int request_id,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int match_count,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int active_ordinal,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bool finished) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((!async_find_started_ && !sync_find_started_) ||
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_id != current_request_id_) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyResults(active_ordinal, match_count, finished);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FindHelper::FindNext(bool forward) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!sync_find_started_ && !async_find_started_)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebFindOptions options;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.forward = forward;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.matchCase = false;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.findNext = true;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents()->Find(current_request_id_, last_search_string_, options);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FindHelper::ClearMatches() {
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents()->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_find_started_ = false;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  async_find_started_ = false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_search_string_.clear();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_match_count_ = -1;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_active_ordinal_ = -1;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FindHelper::StartNewRequest(const base::string16& search_string) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_request_id_ = find_request_id_counter_++;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_search_string_ = search_string;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_match_count_ = -1;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_active_ordinal_ = -1;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FindHelper::NotifyResults(int active_ordinal,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 int match_count,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 bool finished) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Match count or ordinal values set to -1 refer to the received replies.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (match_count == -1)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    match_count = last_match_count_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_match_count_ = match_count;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_ordinal == -1)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_ordinal = last_active_ordinal_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_active_ordinal_ = active_ordinal;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip the update if we don't still have a valid ordinal.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The next update, final or not, should have this information.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!finished && active_ordinal == -1)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Safeguard in case of errors to prevent reporting -1 to the API listeners.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (match_count == -1) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    match_count = 0;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_ordinal == -1) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_ordinal = 0;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebView.FindListener active match ordinals are 0-based while WebKit sends
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1-based ordinals. Still we can receive 0 ordinal in case of no results.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_ordinal = std::max(active_ordinal - 1, 0);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_->OnFindResultReceived(active_ordinal, match_count, finished);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace android_webview
134