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

Side by Side Diff: ios/web/web_state/ui/crw_context_menu_controller.mm

Issue 2640433002: Clean the new CRWContextMenuController (Closed)
Patch Set: clean Created 3 years, 11 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
« no previous file with comments | « ios/web/web_state/context_menu_params_unittest.mm ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ios/web/web_state/ui/crw_context_menu_controller.h" 5 #import "ios/web/web_state/ui/crw_context_menu_controller.h"
6 6
7 #import <objc/runtime.h> 7 #import <objc/runtime.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #import "base/ios/weak_nsobject.h"
11 #include "base/logging.h" 10 #include "base/logging.h"
12 #include "base/mac/foundation_util.h" 11 #include "base/mac/foundation_util.h"
13 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
14 #include "base/strings/sys_string_conversions.h" 13 #include "base/strings/sys_string_conversions.h"
15 #include "components/url_formatter/url_formatter.h"
16 #include "ios/web/public/referrer_util.h"
17 #import "ios/web/public/web_state/context_menu_params.h" 14 #import "ios/web/public/web_state/context_menu_params.h"
18 #import "ios/web/public/web_state/js/crw_js_injection_evaluator.h" 15 #import "ios/web/public/web_state/js/crw_js_injection_evaluator.h"
19 #import "ios/web/public/web_state/ui/crw_context_menu_delegate.h" 16 #import "ios/web/public/web_state/ui/crw_context_menu_delegate.h"
20 17
18 #if !defined(__has_feature) || !__has_feature(objc_arc)
19 #error "This file requires ARC support."
20 #endif
21
21 namespace { 22 namespace {
22 // The long press detection duration must be shorter than the WKWebView's 23 // The long press detection duration must be shorter than the WKWebView's
23 // long click gesture recognizer's minimum duration. That is 0.55s. 24 // long click gesture recognizer's minimum duration. That is 0.55s.
24 // If our detection duration is shorter, our gesture recognizer will fire 25 // If our detection duration is shorter, our gesture recognizer will fire
25 // first, and if it fails the long click gesture (processed simultaneously) 26 // first, and if it fails the long click gesture (processed simultaneously)
26 // still is able to complete. 27 // still is able to complete.
27 const NSTimeInterval kLongPressDurationSeconds = 0.55 - 0.1; 28 const NSTimeInterval kLongPressDurationSeconds = 0.55 - 0.1;
28 29
29 // If there is a movement bigger than |kLongPressMoveDeltaPixels|, the context 30 // If there is a movement bigger than |kLongPressMoveDeltaPixels|, the context
30 // menu will not be triggered. 31 // menu will not be triggered.
31 const CGFloat kLongPressMoveDeltaPixels = 10.0; 32 const CGFloat kLongPressMoveDeltaPixels = 10.0;
32 33
33 // Cancels touch events for the given gesture recognizer. 34 // Cancels touch events for the given gesture recognizer.
34 void CancelTouches(UIGestureRecognizer* gesture_recognizer) { 35 void CancelTouches(UIGestureRecognizer* gesture_recognizer) {
35 if (gesture_recognizer.enabled) { 36 if (gesture_recognizer.enabled) {
36 gesture_recognizer.enabled = NO; 37 gesture_recognizer.enabled = NO;
37 gesture_recognizer.enabled = YES; 38 gesture_recognizer.enabled = YES;
38 } 39 }
39 } 40 }
40 } // namespace 41 } // namespace
41 42
42 @interface CRWContextMenuController ()<UIGestureRecognizerDelegate> 43 @interface CRWContextMenuController ()<UIGestureRecognizerDelegate>
43 44
44 // Sets the specified recognizer to take priority over any recognizers in the
45 // view that have a description containing the specified text fragment.
46 + (void)requireGestureRecognizerToFail:(UIGestureRecognizer*)recognizer
47 inView:(UIView*)view
48 containingDescription:(NSString*)fragment;
49
50 // The |webView|. 45 // The |webView|.
51 @property(nonatomic, readonly) WKWebView* webView; 46 @property(nonatomic, readonly) WKWebView* webView;
52 // The delegate that allow execute javascript. 47 // The delegate that allow execute javascript.
53 @property(nonatomic, readonly) id<CRWJSInjectionEvaluator> injectionEvaluator; 48 @property(nonatomic, readonly) id<CRWJSInjectionEvaluator> injectionEvaluator;
54 // The scroll view of |webView|. 49 // The scroll view of |webView|.
55 @property(nonatomic, readonly) id<CRWContextMenuDelegate> delegate; 50 @property(nonatomic, readonly) id<CRWContextMenuDelegate> delegate;
56 // Returns the x, y offset the content has been scrolled. 51 // Returns the x, y offset the content has been scrolled.
57 @property(nonatomic, readonly) CGPoint scrollPosition; 52 @property(nonatomic, readonly) CGPoint scrollPosition;
58 53
59 // Called when the window has determined there was a long-press and context menu 54 // Called when the window has determined there was a long-press and context menu
60 // must be shown. 55 // must be shown.
61 - (void)showContextMenu:(UIGestureRecognizer*)gestureRecognizer; 56 - (void)showContextMenu:(UIGestureRecognizer*)gestureRecognizer;
62 // Extracts context menu information from the given DOM element.
63 - (web::ContextMenuParams)contextMenuParamsForElement:(NSDictionary*)element;
64 // Cancels all touch events in the web view (long presses, tapping, scrolling). 57 // Cancels all touch events in the web view (long presses, tapping, scrolling).
65 - (void)cancelAllTouches; 58 - (void)cancelAllTouches;
66 // Asynchronously fetches full width of the rendered web page. 59 // Asynchronously fetches full width of the rendered web page.
67 - (void)fetchWebPageWidthWithCompletionHandler:(void (^)(CGFloat))handler; 60 - (void)fetchWebPageWidthWithCompletionHandler:(void (^)(CGFloat))handler;
68 // Asynchronously fetches information about DOM element for the given point (in 61 // Asynchronously fetches information about DOM element for the given point (in
69 // UIView coordinates). |handler| can not be nil. See |_DOMElementForLastTouch| 62 // UIView coordinates). |handler| can not be nil. See |_DOMElementForLastTouch|
70 // for element format description. 63 // for element format description.
71 - (void)fetchDOMElementAtPoint:(CGPoint)point 64 - (void)fetchDOMElementAtPoint:(CGPoint)point
72 completionHandler:(void (^)(NSDictionary*))handler; 65 completionHandler:(void (^)(NSDictionary*))handler;
73 // Sets the value of |_DOMElementForLastTouch|. 66 // Sets the value of |_DOMElementForLastTouch|.
74 - (void)setDOMElementForLastTouch:(NSDictionary*)element; 67 - (void)setDOMElementForLastTouch:(NSDictionary*)element;
75 // Forwards the execution of |script| to |javaScriptDelegate| and if it is nil, 68 // Forwards the execution of |script| to |javaScriptDelegate| and if it is nil,
76 // to |webView|. 69 // to |webView|.
77 - (void)executeJavaScript:(NSString*)script 70 - (void)executeJavaScript:(NSString*)script
78 completionHandler:(web::JavaScriptResultBlock)completionHandler; 71 completionHandler:(web::JavaScriptResultBlock)completionHandler;
79 @end 72 @end
80 73
81 @implementation CRWContextMenuController { 74 @implementation CRWContextMenuController {
82 base::WeakNSProtocol<id<CRWContextMenuDelegate>> _delegate; 75 __weak id<CRWContextMenuDelegate> _delegate;
stkhapugin 2017/01/17 15:13:12 Make the |delegate| property weak and @synthesize
Olivier 2017/01/17 18:02:14 Done.
83 base::WeakNSProtocol<id<CRWJSInjectionEvaluator>> _injectionEvaluator; 76 __weak id<CRWJSInjectionEvaluator> _injectionEvaluator;
stkhapugin 2017/01/17 15:13:12 ditto
Olivier 2017/01/17 18:02:14 Done.
84 base::WeakNSObject<WKWebView> _webView; 77 __weak WKWebView* _webView;
stkhapugin 2017/01/17 15:13:12 ditto
Olivier 2017/01/17 18:02:14 Done.
85 78
86 // Long press recognizer that allows showing context menus. 79 // Long press recognizer that allows showing context menus.
87 base::scoped_nsobject<UILongPressGestureRecognizer> _contextMenuRecognizer; 80 UILongPressGestureRecognizer* _contextMenuRecognizer;
88 // DOM element information for the point where the user made the last touch. 81 // DOM element information for the point where the user made the last touch.
89 // Can be nil if has not been calculated yet. Precalculation is necessary 82 // Can be nil if has not been calculated yet. Precalculation is necessary
90 // because retreiving DOM element relies on async API so element info can not 83 // because retreiving DOM element relies on async API so element info can not
91 // be built on demand. May contain the following keys: @"href", @"src", 84 // be built on demand. May contain the following keys: @"href", @"src",
92 // @"title", @"referrerPolicy". All values are strings. 85 // @"title", @"referrerPolicy". All values are strings.
93 base::scoped_nsobject<NSDictionary> _DOMElementForLastTouch; 86 NSDictionary* _DOMElementForLastTouch;
94 } 87 }
95 88
89 @synthesize delegate = _delegate;
90 @synthesize injectionEvaluator = _injectionEvaluator;
91 @synthesize webView = _webView;
92
96 - (instancetype)initWithWebView:(WKWebView*)webView 93 - (instancetype)initWithWebView:(WKWebView*)webView
97 injectionEvaluator:(id<CRWJSInjectionEvaluator>)injectionEvaluator 94 injectionEvaluator:(id<CRWJSInjectionEvaluator>)injectionEvaluator
98 delegate:(id<CRWContextMenuDelegate>)delegate { 95 delegate:(id<CRWContextMenuDelegate>)delegate {
99 DCHECK(webView); 96 DCHECK(webView);
100 self = [super init]; 97 self = [super init];
101 if (self) { 98 if (self) {
102 _webView.reset(webView); 99 _webView = webView;
103 _delegate.reset(delegate); 100 _delegate = delegate;
104 _injectionEvaluator.reset(injectionEvaluator); 101 _injectionEvaluator = injectionEvaluator;
105 102
106 // The system context menu triggers after 0.55 second. Add a gesture 103 // The system context menu triggers after 0.55 second. Add a gesture
107 // recognizer with a shorter delay to be able to cancel the system menu if 104 // recognizer with a shorter delay to be able to cancel the system menu if
108 // needed. 105 // needed.
109 _contextMenuRecognizer.reset([[UILongPressGestureRecognizer alloc] 106 _contextMenuRecognizer = [[UILongPressGestureRecognizer alloc]
110 initWithTarget:self 107 initWithTarget:self
111 action:@selector(showContextMenu:)]); 108 action:@selector(showContextMenu:)];
112 [_contextMenuRecognizer setMinimumPressDuration:kLongPressDurationSeconds]; 109 [_contextMenuRecognizer setMinimumPressDuration:kLongPressDurationSeconds];
113 [_contextMenuRecognizer setAllowableMovement:kLongPressMoveDeltaPixels]; 110 [_contextMenuRecognizer setAllowableMovement:kLongPressMoveDeltaPixels];
114 [_contextMenuRecognizer setDelegate:self]; 111 [_contextMenuRecognizer setDelegate:self];
115 [_webView addGestureRecognizer:_contextMenuRecognizer]; 112 [_webView addGestureRecognizer:_contextMenuRecognizer];
116 // Certain system gesture handlers are known to conflict with our context
117 // menu handler, causing extra events to fire when the context menu is
118 // active.
119
120 // A number of solutions have been investigated. The lowest-risk solution
121 // appears to be to recurse through the web controller's recognizers,
122 // looking
123 // for fingerprints of the recognizers known to cause problems, which are
124 // then
125 // de-prioritized (below our own long click handler).
126 // Hunting for description fragments of system recognizers is undeniably
127 // brittle for future versions of iOS. If it does break the context menu
128 // events may leak (regressing b/5310177), but the app will otherwise work.
129 // TODO(crbug.com/680930): This code is not needed anymore in iOS9+ and has
130 // to be removed.
131 [CRWContextMenuController
132 requireGestureRecognizerToFail:_contextMenuRecognizer
133 inView:_webView
134 containingDescription:
135 @"action=_highlightLongPressRecognized:"];
136 } 113 }
137 return self; 114 return self;
138 } 115 }
139 116
140 - (WKWebView*)webView {
141 return _webView.get();
142 }
143
144 - (id<CRWContextMenuDelegate>)delegate {
145 return _delegate.get();
146 }
147
148 - (id<CRWJSInjectionEvaluator>)injectionEvaluator {
149 return _injectionEvaluator.get();
150 }
151
152 - (UIScrollView*)webScrollView { 117 - (UIScrollView*)webScrollView {
153 return [_webView scrollView]; 118 return [_webView scrollView];
154 } 119 }
155 120
156 - (CGPoint)scrollPosition { 121 - (CGPoint)scrollPosition {
157 return self.webScrollView.contentOffset; 122 return self.webScrollView.contentOffset;
158 } 123 }
159 124
160 - (void)executeJavaScript:(NSString*)script 125 - (void)executeJavaScript:(NSString*)script
161 completionHandler:(web::JavaScriptResultBlock)completionHandler { 126 completionHandler:(web::JavaScriptResultBlock)completionHandler {
162 if (self.injectionEvaluator) { 127 if (self.injectionEvaluator) {
163 [self.injectionEvaluator executeJavaScript:script 128 [self.injectionEvaluator executeJavaScript:script
164 completionHandler:completionHandler]; 129 completionHandler:completionHandler];
165 } else { 130 } else {
166 [self.webView evaluateJavaScript:script 131 [self.webView evaluateJavaScript:script
167 completionHandler:completionHandler]; 132 completionHandler:completionHandler];
168 } 133 }
169 } 134 }
170 135
171 - (void)showContextMenu:(UIGestureRecognizer*)gestureRecognizer { 136 - (void)showContextMenu:(UIGestureRecognizer*)gestureRecognizer {
172 // If the gesture has already been handled, ignore it. 137 // If the gesture has already been handled, ignore it.
173 if ([gestureRecognizer state] != UIGestureRecognizerStateBegan) 138 if ([gestureRecognizer state] != UIGestureRecognizerStateBegan)
174 return; 139 return;
175 140
176 if (![_DOMElementForLastTouch count]) 141 if (![_DOMElementForLastTouch count])
177 return; 142 return;
178 143
179 web::ContextMenuParams params = 144 web::ContextMenuParams params(_DOMElementForLastTouch);
180 [self contextMenuParamsForElement:_DOMElementForLastTouch.get()]; 145 params.view.reset(_webView);
181 params.view.reset([_webView retain]);
182 params.location = [gestureRecognizer locationInView:_webView]; 146 params.location = [gestureRecognizer locationInView:_webView];
183 if ([_delegate webView:_webView handleContextMenu:params]) { 147 if ([_delegate webView:_webView handleContextMenu:params]) {
184 // Cancelling all touches has the intended side effect of suppressing the 148 // Cancelling all touches has the intended side effect of suppressing the
185 // system's context menu. 149 // system's context menu.
186 [self cancelAllTouches]; 150 [self cancelAllTouches];
187 } 151 }
188 } 152 }
189 153
190 + (void)requireGestureRecognizerToFail:(UIGestureRecognizer*)recognizer
191 inView:(UIView*)view
192 containingDescription:(NSString*)fragment {
193 for (UIGestureRecognizer* iRecognizer in [view gestureRecognizers]) {
194 if (iRecognizer != recognizer) {
195 NSString* description = [iRecognizer description];
196 if ([description rangeOfString:fragment].length) {
197 [iRecognizer requireGestureRecognizerToFail:recognizer];
198 // requireGestureRecognizerToFail: doesn't retain the recognizer, so it
199 // is possible for |iRecognizer| to outlive |recognizer| and end up with
200 // a dangling pointer. Add a retaining associative reference to ensure
201 // that the lifetimes work out.
202 // Note that normally using the value as the key wouldn't make any
203 // sense, but here it's fine since nothing needs to look up the value.
204 objc_setAssociatedObject(view, recognizer, recognizer,
205 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
206 }
207 }
208 }
209 }
210
211 - (web::ContextMenuParams)contextMenuParamsForElement:(NSDictionary*)element {
212 web::ContextMenuParams params;
213 NSString* title = nil;
214 NSString* href = element[@"href"];
215 if (href) {
216 params.link_url = GURL(base::SysNSStringToUTF8(href));
217 if (params.link_url.SchemeIs(url::kJavaScriptScheme)) {
218 title = @"JavaScript";
219 } else {
220 base::string16 URLText = url_formatter::FormatUrl(params.link_url);
221 title = base::SysUTF16ToNSString(URLText);
222 }
223 }
224 NSString* src = element[@"src"];
225 if (src) {
226 params.src_url = GURL(base::SysNSStringToUTF8(src));
227 if (!title)
228 title = [[src copy] autorelease];
229 if ([title hasPrefix:base::SysUTF8ToNSString(url::kDataScheme)])
230 title = nil;
231 }
232 NSString* titleAttribute = element[@"title"];
233 if (titleAttribute)
234 title = titleAttribute;
235 if (title) {
236 params.menu_title.reset([title copy]);
237 }
238 NSString* referrerPolicy = element[@"referrerPolicy"];
239 if (referrerPolicy) {
240 params.referrer_policy =
241 web::ReferrerPolicyFromString(base::SysNSStringToUTF8(referrerPolicy));
242 }
243 NSString* innerText = element[@"innerText"];
244 if ([innerText length] > 0) {
245 params.link_text.reset([innerText copy]);
246 }
247 return params;
248 }
249
250 - (void)cancelAllTouches { 154 - (void)cancelAllTouches {
251 // Disable web view scrolling. 155 // Disable web view scrolling.
252 CancelTouches(self.webView.scrollView.panGestureRecognizer); 156 CancelTouches(self.webView.scrollView.panGestureRecognizer);
253 157
254 // All user gestures are handled by a subview of web view scroll view 158 // All user gestures are handled by a subview of web view scroll view
255 // (WKContentView). 159 // (WKContentView).
256 for (UIView* subview in self.webScrollView.subviews) { 160 for (UIView* subview in self.webScrollView.subviews) {
257 for (UIGestureRecognizer* recognizer in subview.gestureRecognizers) { 161 for (UIGestureRecognizer* recognizer in subview.gestureRecognizers) {
258 CancelTouches(recognizer); 162 CancelTouches(recognizer);
259 } 163 }
260 } 164 }
261 165
262 // Just disabling/enabling the gesture recognizers is not enough to suppress 166 // Just disabling/enabling the gesture recognizers is not enough to suppress
263 // the click handlers on the JS side. This JS performs the function of 167 // the click handlers on the JS side. This JS performs the function of
264 // suppressing these handlers on the JS side. 168 // suppressing these handlers on the JS side.
265 NSString* suppressNextClick = @"__gCrWeb.suppressNextClick()"; 169 NSString* suppressNextClick = @"__gCrWeb.suppressNextClick()";
266 [self executeJavaScript:suppressNextClick completionHandler:nil]; 170 [self executeJavaScript:suppressNextClick completionHandler:nil];
267 } 171 }
268 172
269 - (void)setDOMElementForLastTouch:(NSDictionary*)element { 173 - (void)setDOMElementForLastTouch:(NSDictionary*)element {
270 _DOMElementForLastTouch.reset([element copy]); 174 _DOMElementForLastTouch = [element copy];
271 } 175 }
272 176
273 #pragma mark - 177 #pragma mark -
274 #pragma mark UIGestureRecognizerDelegate 178 #pragma mark UIGestureRecognizerDelegate
275 179
276 - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer 180 - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
277 shouldRecognizeSimultaneouslyWithGestureRecognizer: 181 shouldRecognizeSimultaneouslyWithGestureRecognizer:
278 (UIGestureRecognizer*)otherGestureRecognizer { 182 (UIGestureRecognizer*)otherGestureRecognizer {
279 // Allows the custom UILongPressGestureRecognizer to fire simultaneously with 183 // Allows the custom UILongPressGestureRecognizer to fire simultaneously with
280 // other recognizers. 184 // other recognizers.
281 return YES; 185 return YES;
282 } 186 }
283 187
284 - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer 188 - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
285 shouldReceiveTouch:(UITouch*)touch { 189 shouldReceiveTouch:(UITouch*)touch {
286 // Expect only _contextMenuRecognizer. 190 // Expect only _contextMenuRecognizer.
287 DCHECK([gestureRecognizer isEqual:_contextMenuRecognizer]); 191 DCHECK([gestureRecognizer isEqual:_contextMenuRecognizer]);
288 192
289 // This is custom long press gesture recognizer. By the time the gesture is 193 // This is custom long press gesture recognizer. By the time the gesture is
290 // recognized the web controller needs to know if there is a link under the 194 // recognized the web controller needs to know if there is a link under the
291 // touch. If there a link, the web controller will reject system's context 195 // touch. If there a link, the web controller will reject system's context
292 // menu and show another one. If for some reason context menu info is not 196 // menu and show another one. If for some reason context menu info is not
293 // fetched - system context menu will be shown. 197 // fetched - system context menu will be shown.
294 [self setDOMElementForLastTouch:nil]; 198 [self setDOMElementForLastTouch:nil];
295 base::WeakNSObject<CRWContextMenuController> weakSelf(self); 199 __weak CRWContextMenuController* weakSelf = self;
296 [self fetchDOMElementAtPoint:[touch locationInView:_webView] 200 [self fetchDOMElementAtPoint:[touch locationInView:_webView]
297 completionHandler:^(NSDictionary* element) { 201 completionHandler:^(NSDictionary* element) {
298 [weakSelf setDOMElementForLastTouch:element]; 202 [weakSelf setDOMElementForLastTouch:element];
299 }]; 203 }];
300 return YES; 204 return YES;
301 } 205 }
302 206
303 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer { 207 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer {
304 // Expect only _contextMenuRecognizer. 208 // Expect only _contextMenuRecognizer.
305 DCHECK([gestureRecognizer isEqual:_contextMenuRecognizer]); 209 DCHECK([gestureRecognizer isEqual:_contextMenuRecognizer]);
(...skipping 15 matching lines...) Expand all
321 }]; 225 }];
322 } 226 }
323 227
324 - (void)fetchDOMElementAtPoint:(CGPoint)point 228 - (void)fetchDOMElementAtPoint:(CGPoint)point
325 completionHandler:(void (^)(NSDictionary*))handler { 229 completionHandler:(void (^)(NSDictionary*))handler {
326 DCHECK(handler); 230 DCHECK(handler);
327 // Convert point into web page's coordinate system (which may be scaled and/or 231 // Convert point into web page's coordinate system (which may be scaled and/or
328 // scrolled). 232 // scrolled).
329 CGPoint scrollOffset = self.scrollPosition; 233 CGPoint scrollOffset = self.scrollPosition;
330 CGFloat webViewContentWidth = self.webScrollView.contentSize.width; 234 CGFloat webViewContentWidth = self.webScrollView.contentSize.width;
331 base::WeakNSObject<CRWContextMenuController> weakSelf(self); 235 CRWContextMenuController* weakSelf = self;
332 [self fetchWebPageWidthWithCompletionHandler:^(CGFloat pageWidth) { 236 [self fetchWebPageWidthWithCompletionHandler:^(CGFloat pageWidth) {
333 CGFloat scale = pageWidth / webViewContentWidth; 237 CGFloat scale = pageWidth / webViewContentWidth;
334 CGPoint localPoint = CGPointMake((point.x + scrollOffset.x) * scale, 238 CGPoint localPoint = CGPointMake((point.x + scrollOffset.x) * scale,
335 (point.y + scrollOffset.y) * scale); 239 (point.y + scrollOffset.y) * scale);
336 NSString* const kGetElementScript = 240 NSString* const kGetElementScript =
337 [NSString stringWithFormat:@"__gCrWeb.getElementFromPoint(%g, %g);", 241 [NSString stringWithFormat:@"__gCrWeb.getElementFromPoint(%g, %g);",
338 localPoint.x, localPoint.y]; 242 localPoint.x, localPoint.y];
339 [self executeJavaScript:kGetElementScript 243 [weakSelf executeJavaScript:kGetElementScript
340 completionHandler:^(id element, NSError*) { 244 completionHandler:^(id element, NSError*) {
341 handler(base::mac::ObjCCastStrict<NSDictionary>(element)); 245 handler(base::mac::ObjCCastStrict<NSDictionary>(element));
342 }]; 246 }];
343 }]; 247 }];
344 } 248 }
345 249
346 @end 250 @end
OLDNEW
« no previous file with comments | « ios/web/web_state/context_menu_params_unittest.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698