Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: ios/chrome/browser/find_in_page/js_findinpage_manager.mm

Issue 1023813003: [iOS] Upstream ios/chrome/browser/find_in_page (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@upstreamAutofill
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/find_in_page/js_findinpage_manager.h"
6
7 #include <string>
8
9 #import "base/ios/weak_nsobject.h"
10 #include "base/json/json_reader.h"
11 #include "base/json/string_escape.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/values.h"
16 #import "ios/chrome/browser/find_in_page/find_in_page_model.h"
17 #import "ios/web/public/web_state/js/crw_js_early_script_manager.h"
18
19 namespace {
20
21 // Global variable defined in find_in_page.js that can be used for testing
22 // whether JavaScript bas heen loaded.
23 NSString* const kFindInPageBeacon = @"window.__gCrWeb.findInPage";
24
25 // Initializes Find In Page JavaScript with the width and height of the window.
26 NSString* const kFindInPageInit = @"window.__gCrWeb.findInPage && "
27 "window.__gCrWeb.findInPage.init(%.f, %.f);";
28
29 // This will only do verbatim matches.
30 // The timeout of 100ms is hardcoded into this string so we don't have
31 // to spend any time at runtime to format this constant into another constant.
32 NSString* const kFindInPageVerbatim =
33 @"window.__gCrWeb.findInPage && "
34 "window.__gCrWeb.findInPage.highlightWord(%@, false, 100.0);";
35
36 // The timeout of 100ms is hardcoded into this string so we don't have
37 // to spend any time at runtime to format this constant into another constant.
38 NSString* const kFindInPagePump =
39 @"window.__gCrWeb.findInPage && "
40 "window.__gCrWeb.findInPage.pumpSearch(100.0);";
41
42 NSString* const kFindInPagePrev = @"window.__gCrWeb.findInPage && "
43 "window.__gCrWeb.findInPage.goPrev();";
44
45 NSString* const kFindInPageNext = @"window.__gCrWeb.findInPage && "
46 "window.__gCrWeb.findInPage.goNext();";
47
48 NSString* const kFindInPageDisable = @"window.__gCrWeb.findInPage && "
49 "window.__gCrWeb.findInPage.disable();";
50
51 NSString* const kFindInPagePending = @"[false]";
52
53 const FindInPageEntry kFindInPageEntryZero = {{0.0, 0.0}, 0};
54
55 } // namespace
56
57 @interface JsFindinpageManager ()
58 // Update find in page model with results, return true if fip completes or
59 // false if still pending and requires pumping. If |point| is not nil, it will
60 // contain the scroll position upon return.
61 - (BOOL)processFindInPageResult:(NSString*)result
62 scrollPosition:(CGPoint*)point;
63 // Updates find in page model with results. Calls |completionHandler| with the
64 // the result of the processing and the new scroll position if successfull. If
65 // |completionHandler| is called with NO, further pumping is required.
66 // |completionHandler| cannot be nil.
67 - (void)processFindInPagePumpResult:(NSString*)result
68 completionHandler:(void (^)(BOOL, CGPoint))completionHandler;
69 // Helper functions to extract FindInPageEntry from JSON.
70 - (FindInPageEntry)findInPageEntryForJson:(NSString*)jsonStr;
71 - (FindInPageEntry)entryForListValue:(base::ListValue*)position;
72 // Executes |script| which is a piece of JavaScript to move to the next or
73 // previous element in the page and executes |completionHandler| after moving
74 // with the new scroll position passed in.
75 - (void)moveHighlightByEvaluatingJavaScript:(NSString*)script
76 completionHandler:
77 (void (^)(CGPoint))completionHandler;
78 // Updates the current match index and its found position in the model.
79 - (void)updateIndex:(NSInteger)index atPoint:(CGPoint)point;
80 @end
81
82 @implementation JsFindinpageManager
83
84 - (FindInPageModel*)findInPageModel {
85 if (!findInPageModel_)
86 findInPageModel_.reset([[FindInPageModel alloc] init]);
87 return findInPageModel_.get();
88 }
89
90 - (void)setWidth:(CGFloat)width height:(CGFloat)height {
91 NSString* javaScript =
92 [NSString stringWithFormat:kFindInPageInit, width, height];
93 [self evaluate:javaScript stringResultHandler:nil];
94 }
95
96 - (void)findString:(NSString*)query
97 completionHandler:(void (^)(BOOL, CGPoint))completionHandler {
98 DCHECK(completionHandler);
99 // Save the query in the model before searching.
100 [findInPageModel_ updateQuery:query matches:0];
101
102 // Escape |query| before passing to js.
103 std::string escapedJson;
104 base::EscapeJSONString(base::SysNSStringToUTF16(query), true, &escapedJson);
105 NSString* jsonQuery =
106 [NSString stringWithFormat:kFindInPageVerbatim,
107 base::SysUTF8ToNSString(escapedJson.c_str())];
108 base::WeakNSObject<JsFindinpageManager> weakSelf(self);
109 [self evaluate:jsonQuery
110 stringResultHandler:^(NSString* result, NSError* error) {
111 [weakSelf processFindInPagePumpResult:result
112 completionHandler:completionHandler];
113 }];
114 }
115
116 - (void)pumpWithCompletionHandler:(void (^)(BOOL, CGPoint))completionHandler {
117 DCHECK(completionHandler);
118 base::WeakNSObject<JsFindinpageManager> weakSelf(self);
119 [self evaluate:kFindInPagePump
120 stringResultHandler:^(NSString* result, NSError* error) {
121 // TODO(shreyasv): What to do here if this returns an NSError in the
122 // WKWebView version.
123 [weakSelf processFindInPagePumpResult:result
124 completionHandler:completionHandler];
125 }];
126 }
127
128 - (void)nextMatchWithCompletionHandler:(void (^)(CGPoint))completionHandler {
129 [self moveHighlightByEvaluatingJavaScript:kFindInPageNext
130 completionHandler:completionHandler];
131 }
132
133 - (void)previousMatchWithCompletionHandler:
134 (void (^)(CGPoint))completionHandler {
135 [self moveHighlightByEvaluatingJavaScript:kFindInPagePrev
136 completionHandler:completionHandler];
137 }
138
139 - (void)moveHighlightByEvaluatingJavaScript:(NSString*)script
140 completionHandler:
141 (void (^)(CGPoint))completionHandler {
142 base::WeakNSObject<JsFindinpageManager> weakSelf(self);
143 [self evaluate:script
144 stringResultHandler:^(NSString* result, NSError* error) {
145 base::WeakNSObject<JsFindinpageManager> strongSelf([weakSelf retain]);
146 if (!strongSelf)
147 return;
148 DCHECK(!error);
149 FindInPageEntry entry = kFindInPageEntryZero;
150 if (![result isEqualToString:kFindInPagePending])
151 entry = [strongSelf findInPageEntryForJson:result];
152 CGPoint newPoint = entry.point;
153 [strongSelf updateIndex:entry.index atPoint:newPoint];
154 if (completionHandler)
155 completionHandler(newPoint);
156 }];
157 }
158
159 - (void)disableWithCompletionHandler:(ProceduralBlock)completionHandler {
160 DCHECK(completionHandler);
161 base::WeakNSObject<FindInPageModel> weakFindInPageModel(findInPageModel_);
162 [self evaluate:kFindInPageDisable
163 stringResultHandler:^(NSString* result, NSError* error) {
164 [weakFindInPageModel setEnabled:NO];
165 completionHandler();
166 }];
167 }
168
169 #pragma mark -
170 #pragma mark FindInPageEntry
171
172 - (BOOL)processFindInPageResult:(NSString*)result
173 scrollPosition:(CGPoint*)point {
174 if (!result)
175 return NO;
176
177 // Parse JSONs.
178 std::string json([result UTF8String]);
179 scoped_ptr<base::Value> root(base::JSONReader::Read(json, false));
180 if (!root.get())
181 return YES;
182 if (!root->IsType(base::Value::TYPE_LIST))
183 return YES;
184
185 base::ListValue* resultList = static_cast<base::ListValue*>(root.get());
186 DCHECK(resultList);
187 if (resultList) {
188 if (resultList->GetSize() == 2) {
189 int numHighlighted = 0;
190 if (resultList->GetInteger(0, &numHighlighted)) {
191 if (numHighlighted > 0) {
192 base::ListValue* position;
193 if (resultList->GetList(1, &position)) {
194 [findInPageModel_ updateQuery:nil matches:numHighlighted];
195 // Scroll to first match.
196 FindInPageEntry entry = [self entryForListValue:position];
197 [findInPageModel_ updateIndex:entry.index atPoint:entry.point];
198 if (point)
199 *point = entry.point;
200 }
201 }
202 }
203 }
204 }
205 return YES;
206 }
207
208 - (void)processFindInPagePumpResult:(NSString*)result
209 completionHandler:(void (^)(BOOL, CGPoint))completionHandler {
210 CGPoint point = CGPointZero;
211 if ([result isEqualToString:kFindInPagePending]) {
212 completionHandler(NO, point);
213 }
214 // TODO(shreyasv): Inline this call from the logic from the above function
215 // and remove the above function.
216 BOOL processFIPResult =
217 [self processFindInPageResult:result scrollPosition:&point];
218 completionHandler(processFIPResult, point);
219 }
220
221 - (void)updateIndex:(NSInteger)index atPoint:(CGPoint)point {
222 [findInPageModel_ updateIndex:index atPoint:point];
223 }
224
225 - (FindInPageEntry)findInPageEntryForJson:(NSString*)jsonStr {
226 std::string json([jsonStr UTF8String]);
227 scoped_ptr<base::Value> root(base::JSONReader::Read(json, false));
228 if (!root.get())
229 return kFindInPageEntryZero;
230
231 if (!root->IsType(base::Value::TYPE_LIST))
232 return kFindInPageEntryZero;
233
234 base::ListValue* position = static_cast<base::ListValue*>(root.get());
235 return [self entryForListValue:position];
236 }
237
238 - (FindInPageEntry)entryForListValue:(base::ListValue*)position {
239 if (!position)
240 return kFindInPageEntryZero;
241
242 // Position should always be of length 3, from [index,x,y].
243 DCHECK(position->GetSize() == 3);
244 if (position->GetSize() != 3)
245 return kFindInPageEntryZero;
246
247 // The array position comes from the JSON string [index, x, y], which
248 // represents the index of the currently found string, and the x and y
249 // position necessary to center that string. Pull out that data into a
250 // FindInPageEntry struct.
251 int index;
252 double x = 0, y = 0;
253 position->GetInteger(0, &index);
254 position->GetDouble(1, &x);
255 position->GetDouble(2, &y);
256 FindInPageEntry entry;
257 entry.index = index;
258 entry.point.x = x;
259 entry.point.y = y;
260 return entry;
261 }
262
263 #pragma mark -
264 #pragma mark ProtectedMethods
265
266 - (NSString*)scriptPath {
267 return @"find_in_page";
268 }
269
270 - (NSString*)presenceBeacon {
271 return kFindInPageBeacon;
272 }
273
274 - (NSArray*)directDependencies {
275 return @[ [CRWJSEarlyScriptManager class] ];
276 }
277
278 @end
OLDNEW
« no previous file with comments | « ios/chrome/browser/find_in_page/js_findinpage_manager.h ('k') | ios/chrome/browser/find_in_page/resources/find_in_page.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698