• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "android_webview/browser/find_helper.h"
6 
7 #include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h"
8 #include "base/message_loop/message_loop.h"
9 #include "content/public/browser/render_view_host.h"
10 #include "content/public/browser/web_contents.h"
11 #include "content/public/common/stop_find_action.h"
12 #include "third_party/WebKit/public/web/WebFindOptions.h"
13 
14 using content::WebContents;
15 using blink::WebFindOptions;
16 
17 namespace android_webview {
18 
FindHelper(WebContents * web_contents)19 FindHelper::FindHelper(WebContents* web_contents)
20     : WebContentsObserver(web_contents),
21       listener_(NULL),
22       async_find_started_(false),
23       sync_find_started_(false),
24       find_request_id_counter_(0),
25       current_request_id_(0),
26       last_match_count_(-1),
27       last_active_ordinal_(-1),
28       weak_factory_(this) {
29 }
30 
~FindHelper()31 FindHelper::~FindHelper() {
32 }
33 
SetListener(Listener * listener)34 void FindHelper::SetListener(Listener* listener) {
35   listener_ = listener;
36 }
37 
FindAllAsync(const base::string16 & search_string)38 void FindHelper::FindAllAsync(const base::string16& search_string) {
39   // Stop any ongoing asynchronous request.
40   web_contents()->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION);
41 
42   sync_find_started_ = false;
43   async_find_started_ = true;
44 
45   WebFindOptions options;
46   options.forward = true;
47   options.matchCase = false;
48   options.findNext = false;
49 
50   StartNewRequest(search_string);
51   web_contents()->Find(current_request_id_, search_string, options);
52 }
53 
HandleFindReply(int request_id,int match_count,int active_ordinal,bool finished)54 void FindHelper::HandleFindReply(int request_id,
55                                    int match_count,
56                                    int active_ordinal,
57                                    bool finished) {
58   if ((!async_find_started_ && !sync_find_started_) ||
59       request_id != current_request_id_) {
60     return;
61   }
62 
63   NotifyResults(active_ordinal, match_count, finished);
64 }
65 
FindNext(bool forward)66 void FindHelper::FindNext(bool forward) {
67   if (!sync_find_started_ && !async_find_started_)
68     return;
69 
70   WebFindOptions options;
71   options.forward = forward;
72   options.matchCase = false;
73   options.findNext = true;
74 
75   web_contents()->Find(current_request_id_, last_search_string_, options);
76 }
77 
ClearMatches()78 void FindHelper::ClearMatches() {
79   web_contents()->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION);
80 
81   sync_find_started_ = false;
82   async_find_started_ = false;
83   last_search_string_.clear();
84   last_match_count_ = -1;
85   last_active_ordinal_ = -1;
86 }
87 
StartNewRequest(const base::string16 & search_string)88 void FindHelper::StartNewRequest(const base::string16& search_string) {
89   current_request_id_ = find_request_id_counter_++;
90   last_search_string_ = search_string;
91   last_match_count_ = -1;
92   last_active_ordinal_ = -1;
93 }
94 
NotifyResults(int active_ordinal,int match_count,bool finished)95 void FindHelper::NotifyResults(int active_ordinal,
96                                  int match_count,
97                                  bool finished) {
98   // Match count or ordinal values set to -1 refer to the received replies.
99   if (match_count == -1)
100     match_count = last_match_count_;
101   else
102     last_match_count_ = match_count;
103 
104   if (active_ordinal == -1)
105     active_ordinal = last_active_ordinal_;
106   else
107     last_active_ordinal_ = active_ordinal;
108 
109   // Skip the update if we don't still have a valid ordinal.
110   // The next update, final or not, should have this information.
111   if (!finished && active_ordinal == -1)
112     return;
113 
114   // Safeguard in case of errors to prevent reporting -1 to the API listeners.
115   if (match_count == -1) {
116     NOTREACHED();
117     match_count = 0;
118   }
119 
120   if (active_ordinal == -1) {
121     NOTREACHED();
122     active_ordinal = 0;
123   }
124 
125   // WebView.FindListener active match ordinals are 0-based while WebKit sends
126   // 1-based ordinals. Still we can receive 0 ordinal in case of no results.
127   active_ordinal = std::max(active_ordinal - 1, 0);
128 
129   if (listener_)
130     listener_->OnFindResultReceived(active_ordinal, match_count, finished);
131 }
132 
133 }  // namespace android_webview
134