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

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

Issue 2627093003: Reuse context menu in StaticHTMLViewController (Closed)
Patch Set: cleaning 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
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 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 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_web_controller.h" 5 #import "ios/web/web_state/ui/crw_web_controller.h"
6 6
7 #import <WebKit/WebKit.h> 7 #import <WebKit/WebKit.h>
8 8
9 #import <objc/runtime.h> 9 #import <objc/runtime.h>
10 #include <stddef.h> 10 #include <stddef.h>
(...skipping 19 matching lines...) Expand all
30 #import "base/mac/scoped_nsobject.h" 30 #import "base/mac/scoped_nsobject.h"
31 #include "base/memory/ptr_util.h" 31 #include "base/memory/ptr_util.h"
32 #include "base/metrics/histogram.h" 32 #include "base/metrics/histogram.h"
33 #include "base/metrics/user_metrics.h" 33 #include "base/metrics/user_metrics.h"
34 #include "base/metrics/user_metrics_action.h" 34 #include "base/metrics/user_metrics_action.h"
35 #include "base/strings/string_util.h" 35 #include "base/strings/string_util.h"
36 #include "base/strings/sys_string_conversions.h" 36 #include "base/strings/sys_string_conversions.h"
37 #include "base/strings/utf_string_conversions.h" 37 #include "base/strings/utf_string_conversions.h"
38 #include "base/time/time.h" 38 #include "base/time/time.h"
39 #include "base/values.h" 39 #include "base/values.h"
40 #include "components/url_formatter/url_formatter.h"
41 #import "ios/net/http_response_headers_util.h" 40 #import "ios/net/http_response_headers_util.h"
42 #import "ios/net/nsurlrequest_util.h" 41 #import "ios/net/nsurlrequest_util.h"
43 #include "ios/web/history_state_util.h" 42 #include "ios/web/history_state_util.h"
44 #import "ios/web/interstitials/web_interstitial_impl.h" 43 #import "ios/web/interstitials/web_interstitial_impl.h"
45 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" 44 #import "ios/web/navigation/crw_session_certificate_policy_manager.h"
46 #import "ios/web/navigation/crw_session_controller.h" 45 #import "ios/web/navigation/crw_session_controller.h"
47 #import "ios/web/navigation/crw_session_entry.h" 46 #import "ios/web/navigation/crw_session_entry.h"
48 #import "ios/web/navigation/navigation_item_impl.h" 47 #import "ios/web/navigation/navigation_item_impl.h"
49 #import "ios/web/navigation/navigation_manager_impl.h" 48 #import "ios/web/navigation/navigation_manager_impl.h"
50 #include "ios/web/net/cert_host_pair.h" 49 #include "ios/web/net/cert_host_pair.h"
(...skipping 15 matching lines...) Expand all
66 #include "ios/web/public/web_kit_constants.h" 65 #include "ios/web/public/web_kit_constants.h"
67 #import "ios/web/public/web_state/context_menu_params.h" 66 #import "ios/web/public/web_state/context_menu_params.h"
68 #include "ios/web/public/web_state/credential.h" 67 #include "ios/web/public/web_state/credential.h"
69 #import "ios/web/public/web_state/crw_web_controller_observer.h" 68 #import "ios/web/public/web_state/crw_web_controller_observer.h"
70 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h" 69 #import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
71 #include "ios/web/public/web_state/js/credential_util.h" 70 #include "ios/web/public/web_state/js/credential_util.h"
72 #import "ios/web/public/web_state/js/crw_js_injection_manager.h" 71 #import "ios/web/public/web_state/js/crw_js_injection_manager.h"
73 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" 72 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
74 #include "ios/web/public/web_state/page_display_state.h" 73 #include "ios/web/public/web_state/page_display_state.h"
75 #import "ios/web/public/web_state/ui/crw_content_view.h" 74 #import "ios/web/public/web_state/ui/crw_content_view.h"
75 #import "ios/web/public/web_state/ui/crw_context_menu_delegate.h"
76 #import "ios/web/public/web_state/ui/crw_native_content.h" 76 #import "ios/web/public/web_state/ui/crw_native_content.h"
77 #import "ios/web/public/web_state/ui/crw_native_content_provider.h" 77 #import "ios/web/public/web_state/ui/crw_native_content_provider.h"
78 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h" 78 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h"
79 #include "ios/web/public/web_state/url_verification_constants.h" 79 #include "ios/web/public/web_state/url_verification_constants.h"
80 #import "ios/web/public/web_state/web_state.h" 80 #import "ios/web/public/web_state/web_state.h"
81 #include "ios/web/public/webui/web_ui_ios.h" 81 #include "ios/web/public/webui/web_ui_ios.h"
82 #import "ios/web/web_state/blocked_popup_info.h" 82 #import "ios/web/web_state/blocked_popup_info.h"
83 #import "ios/web/web_state/crw_pass_kit_downloader.h" 83 #import "ios/web/web_state/crw_pass_kit_downloader.h"
84 #import "ios/web/web_state/crw_web_view_proxy_impl.h" 84 #import "ios/web/web_state/crw_web_view_proxy_impl.h"
85 #import "ios/web/web_state/error_translation_util.h" 85 #import "ios/web/web_state/error_translation_util.h"
86 #import "ios/web/web_state/js/crw_js_plugin_placeholder_manager.h" 86 #import "ios/web/web_state/js/crw_js_plugin_placeholder_manager.h"
87 #import "ios/web/web_state/js/crw_js_post_request_loader.h" 87 #import "ios/web/web_state/js/crw_js_post_request_loader.h"
88 #import "ios/web/web_state/js/crw_js_window_id_manager.h" 88 #import "ios/web/web_state/js/crw_js_window_id_manager.h"
89 #import "ios/web/web_state/page_viewport_state.h" 89 #import "ios/web/web_state/page_viewport_state.h"
90 #import "ios/web/web_state/ui/crw_context_menu_controller.h"
90 #import "ios/web/web_state/ui/crw_swipe_recognizer_provider.h" 91 #import "ios/web/web_state/ui/crw_swipe_recognizer_provider.h"
91 #import "ios/web/web_state/ui/crw_web_controller.h" 92 #import "ios/web/web_state/ui/crw_web_controller.h"
92 #import "ios/web/web_state/ui/crw_web_controller_container_view.h" 93 #import "ios/web/web_state/ui/crw_web_controller_container_view.h"
93 #import "ios/web/web_state/ui/crw_wk_navigation_states.h" 94 #import "ios/web/web_state/ui/crw_wk_navigation_states.h"
94 #import "ios/web/web_state/ui/crw_wk_script_message_router.h" 95 #import "ios/web/web_state/ui/crw_wk_script_message_router.h"
95 #import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h" 96 #import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h"
96 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" 97 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
97 #import "ios/web/web_state/web_controller_observer_bridge.h" 98 #import "ios/web/web_state/web_controller_observer_bridge.h"
98 #include "ios/web/web_state/web_state_facade_delegate.h" 99 #include "ios/web/web_state/web_state_facade_delegate.h"
99 #import "ios/web/web_state/web_state_impl.h" 100 #import "ios/web/web_state/web_state_impl.h"
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 211
211 // States for external URL requests. This enum is used in UMA and 212 // States for external URL requests. This enum is used in UMA and
212 // entries should not be re-ordered or deleted. 213 // entries should not be re-ordered or deleted.
213 enum ExternalURLRequestStatus { 214 enum ExternalURLRequestStatus {
214 MAIN_FRAME_ALLOWED = 0, 215 MAIN_FRAME_ALLOWED = 0,
215 SUBFRAME_ALLOWED, 216 SUBFRAME_ALLOWED,
216 SUBFRAME_BLOCKED, 217 SUBFRAME_BLOCKED,
217 NUM_EXTERNAL_URL_REQUEST_STATUS 218 NUM_EXTERNAL_URL_REQUEST_STATUS
218 }; 219 };
219 220
220 // Cancels touch events for the given gesture recognizer.
221 void CancelTouches(UIGestureRecognizer* gesture_recognizer) {
222 if (gesture_recognizer.enabled) {
223 gesture_recognizer.enabled = NO;
224 gesture_recognizer.enabled = YES;
225 }
226 }
227
228 // Utility function for getting the source of NSErrors received by WKWebViews. 221 // Utility function for getting the source of NSErrors received by WKWebViews.
229 WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { 222 WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
230 DCHECK(error); 223 DCHECK(error);
231 return static_cast<WKWebViewErrorSource>( 224 return static_cast<WKWebViewErrorSource>(
232 [error.userInfo[kWKWebViewErrorSourceKey] integerValue]); 225 [error.userInfo[kWKWebViewErrorSourceKey] integerValue]);
233 } 226 }
234 // Utility function for converting the WKWebViewErrorSource to the NSError 227 // Utility function for converting the WKWebViewErrorSource to the NSError
235 // received by WKWebViews. 228 // received by WKWebViews.
236 NSError* WKWebViewErrorWithSource(NSError* error, WKWebViewErrorSource source) { 229 NSError* WKWebViewErrorWithSource(NSError* error, WKWebViewErrorSource source) {
237 DCHECK(error); 230 DCHECK(error);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 - (instancetype)init { 270 - (instancetype)init {
278 if ((self = [super init])) { 271 if ((self = [super init])) {
279 _propertyReleaser_CRWWebControllerPendingNavigationInfo.Init( 272 _propertyReleaser_CRWWebControllerPendingNavigationInfo.Init(
280 self, [CRWWebControllerPendingNavigationInfo class]); 273 self, [CRWWebControllerPendingNavigationInfo class]);
281 _navigationType = WKNavigationTypeOther; 274 _navigationType = WKNavigationTypeOther;
282 } 275 }
283 return self; 276 return self;
284 } 277 }
285 @end 278 @end
286 279
287 @interface CRWWebController ()<CRWNativeContentDelegate, 280 @interface CRWWebController ()<CRWContextMenuDelegate,
281 CRWContextMenuJavaScriptDelegate,
282 CRWNativeContentDelegate,
288 CRWSSLStatusUpdaterDataSource, 283 CRWSSLStatusUpdaterDataSource,
289 CRWSSLStatusUpdaterDelegate, 284 CRWSSLStatusUpdaterDelegate,
290 CRWWebControllerContainerViewDelegate, 285 CRWWebControllerContainerViewDelegate,
291 CRWWebViewScrollViewProxyObserver, 286 CRWWebViewScrollViewProxyObserver,
292 WKNavigationDelegate, 287 WKNavigationDelegate,
293 WKUIDelegate> { 288 WKUIDelegate> {
294 base::WeakNSProtocol<id<CRWWebDelegate>> _delegate; 289 base::WeakNSProtocol<id<CRWWebDelegate>> _delegate;
295 base::WeakNSProtocol<id<CRWWebUserInterfaceDelegate>> _UIDelegate; 290 base::WeakNSProtocol<id<CRWWebUserInterfaceDelegate>> _UIDelegate;
296 base::WeakNSProtocol<id<CRWNativeContentProvider>> _nativeProvider; 291 base::WeakNSProtocol<id<CRWNativeContentProvider>> _nativeProvider;
297 base::WeakNSProtocol<id<CRWSwipeRecognizerProvider>> _swipeRecognizerProvider; 292 base::WeakNSProtocol<id<CRWSwipeRecognizerProvider>> _swipeRecognizerProvider;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 // next creation. 351 // next creation.
357 BOOL _usePlaceholderOverlay; 352 BOOL _usePlaceholderOverlay;
358 // The next time the view is requested, reload the page (using the placeholder 353 // The next time the view is requested, reload the page (using the placeholder
359 // overlay until it's loaded). 354 // overlay until it's loaded).
360 BOOL _requireReloadOnDisplay; 355 BOOL _requireReloadOnDisplay;
361 // Overlay view used instead of webView. 356 // Overlay view used instead of webView.
362 base::scoped_nsobject<UIImageView> _placeholderOverlayView; 357 base::scoped_nsobject<UIImageView> _placeholderOverlayView;
363 // The touch tracking recognizer allowing us to decide if a navigation is 358 // The touch tracking recognizer allowing us to decide if a navigation is
364 // started by the user. 359 // started by the user.
365 base::scoped_nsobject<CRWTouchTrackingRecognizer> _touchTrackingRecognizer; 360 base::scoped_nsobject<CRWTouchTrackingRecognizer> _touchTrackingRecognizer;
366 // Long press recognizer that allows showing context menus. 361 // The controller that tracks long press and check context menu trigger.
367 base::scoped_nsobject<UILongPressGestureRecognizer> _contextMenuRecognizer; 362 base::scoped_nsobject<CRWContextMenuController> _contextMenuController;
368 // DOM element information for the point where the user made the last touch.
369 // Can be nil if has not been calculated yet. Precalculation is necessary
370 // because retreiving DOM element relies on async API so element info can not
371 // be built on demand. May contain the following keys: @"href", @"src",
372 // @"title", @"referrerPolicy". All values are strings. Used for showing
373 // context menus.
374 base::scoped_nsobject<NSDictionary> _DOMElementForLastTouch;
375 // Whether a click is in progress. 363 // Whether a click is in progress.
376 BOOL _clickInProgress; 364 BOOL _clickInProgress;
377 // Data on the recorded last user interaction. 365 // Data on the recorded last user interaction.
378 std::unique_ptr<web::UserInteractionEvent> _lastUserInteraction; 366 std::unique_ptr<web::UserInteractionEvent> _lastUserInteraction;
379 // YES if there has been user interaction with views owned by this controller. 367 // YES if there has been user interaction with views owned by this controller.
380 BOOL _userInteractedWithWebController; 368 BOOL _userInteractedWithWebController;
381 // The time of the last page transfer start, measured in seconds since Jan 1 369 // The time of the last page transfer start, measured in seconds since Jan 1
382 // 2001. 370 // 2001.
383 CFAbsoluteTime _lastTransferTimeInSeconds; 371 CFAbsoluteTime _lastTransferTimeInSeconds;
384 // Default URL (about:blank). 372 // Default URL (about:blank).
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 - (void)prepareToApplyWebViewScrollZoomScale; 716 - (void)prepareToApplyWebViewScrollZoomScale;
729 // Calls the zoom-completion UIScrollViewDelegate callbacks on the web view. 717 // Calls the zoom-completion UIScrollViewDelegate callbacks on the web view.
730 // This is called after |-applyWebViewScrollZoomScaleFromScrollState:|. 718 // This is called after |-applyWebViewScrollZoomScaleFromScrollState:|.
731 - (void)finishApplyingWebViewScrollZoomScale; 719 - (void)finishApplyingWebViewScrollZoomScale;
732 // Sets zoom scale value for webview scroll view from |zoomState|. 720 // Sets zoom scale value for webview scroll view from |zoomState|.
733 - (void)applyWebViewScrollZoomScaleFromZoomState: 721 - (void)applyWebViewScrollZoomScaleFromZoomState:
734 (const web::PageZoomState&)zoomState; 722 (const web::PageZoomState&)zoomState;
735 // Sets scroll offset value for webview scroll view from |scrollState|. 723 // Sets scroll offset value for webview scroll view from |scrollState|.
736 - (void)applyWebViewScrollOffsetFromScrollState: 724 - (void)applyWebViewScrollOffsetFromScrollState:
737 (const web::PageScrollState&)scrollState; 725 (const web::PageScrollState&)scrollState;
738 // Asynchronously fetches full width of the rendered web page.
739 - (void)fetchWebPageWidthWithCompletionHandler:(void (^)(CGFloat))handler;
740 // Asynchronously fetches information about DOM element for the given point (in
741 // UIView coordinates). |handler| can not be nil. See |_DOMElementForLastTouch|
742 // for element format description.
743 - (void)fetchDOMElementAtPoint:(CGPoint)point
744 completionHandler:(void (^)(NSDictionary*))handler;
745 // Extracts context menu information from the given DOM element.
746 - (web::ContextMenuParams)contextMenuParamsForElement:(NSDictionary*)element;
747 // Sets the value of |_DOMElementForLastTouch|.
748 - (void)setDOMElementForLastTouch:(NSDictionary*)element;
749 // Called when the window has determined there was a long-press and context menu
750 // must be shown.
751 - (void)showContextMenu:(UIGestureRecognizer*)gestureRecognizer;
752 // Cancels all touch events in the web view (long presses, tapping, scrolling).
753 - (void)cancelAllTouches;
754 // Returns the referrer for the current page. 726 // Returns the referrer for the current page.
755 - (web::Referrer)currentReferrer; 727 - (web::Referrer)currentReferrer;
756 // Asynchronously returns the referrer policy for the current page. 728 // Asynchronously returns the referrer policy for the current page.
757 - (void)queryPageReferrerPolicy:(void (^)(NSString*))responseHandler; 729 - (void)queryPageReferrerPolicy:(void (^)(NSString*))responseHandler;
758 // Adds a new CRWSessionEntry with the given URL and state object to the history 730 // Adds a new CRWSessionEntry with the given URL and state object to the history
759 // stack. A state object is a serialized generic JavaScript object that contains 731 // stack. A state object is a serialized generic JavaScript object that contains
760 // details of the UI's state for a given CRWSessionEntry/URL. 732 // details of the UI's state for a given CRWSessionEntry/URL.
761 // TODO(stuartmorgan): Move the pushState/replaceState logic into 733 // TODO(stuartmorgan): Move the pushState/replaceState logic into
762 // NavigationManager. 734 // NavigationManager.
763 - (void)pushStateWithPageURL:(const GURL&)pageURL 735 - (void)pushStateWithPageURL:(const GURL&)pageURL
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 - (void)createWebUIForURL:(const GURL&)URL; 954 - (void)createWebUIForURL:(const GURL&)URL;
983 // Clears WebUI, if one exists. 955 // Clears WebUI, if one exists.
984 - (void)clearWebUI; 956 - (void)clearWebUI;
985 957
986 @end 958 @end
987 959
988 namespace { 960 namespace {
989 961
990 NSString* const kReferrerHeaderName = @"Referer"; // [sic] 962 NSString* const kReferrerHeaderName = @"Referer"; // [sic]
991 963
992 // The long press detection duration must be shorter than the UIWebView's
993 // long click gesture recognizer's minimum duration. That is 0.55s.
994 // If our detection duration is shorter, our gesture recognizer will fire
995 // first, and if it fails the long click gesture (processed simultaneously)
996 // still is able to complete.
997 const NSTimeInterval kLongPressDurationSeconds = 0.55 - 0.1;
998 const CGFloat kLongPressMoveDeltaPixels = 10.0;
999
1000 // The duration of the period following a screen touch during which the user is 964 // The duration of the period following a screen touch during which the user is
1001 // still considered to be interacting with the page. 965 // still considered to be interacting with the page.
1002 const NSTimeInterval kMaximumDelayForUserInteractionInSeconds = 2; 966 const NSTimeInterval kMaximumDelayForUserInteractionInSeconds = 2;
1003 967
1004 // URLs that are fed into UIWebView as history push/replace get escaped, 968 // URLs that are fed into UIWebView as history push/replace get escaped,
1005 // potentially changing their format. Code that attempts to determine whether a 969 // potentially changing their format. Code that attempts to determine whether a
1006 // URL hasn't changed can be confused by those differences though, so method 970 // URL hasn't changed can be confused by those differences though, so method
1007 // will round-trip a URL through the escaping process so that it can be adjusted 971 // will round-trip a URL through the escaping process so that it can be adjusted
1008 // pre-storing, to allow later comparisons to work as expected. 972 // pre-storing, to allow later comparisons to work as expected.
1009 GURL URLEscapedForHistory(const GURL& url) { 973 GURL URLEscapedForHistory(const GURL& url) {
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1297 // Mark the destruction sequence has started, in case someone else holds a 1261 // Mark the destruction sequence has started, in case someone else holds a
1298 // strong reference and tries to continue using the tab. 1262 // strong reference and tries to continue using the tab.
1299 _isBeingDestroyed = YES; 1263 _isBeingDestroyed = YES;
1300 1264
1301 // Remove the web view now. Otherwise, delegate callbacks occur. 1265 // Remove the web view now. Otherwise, delegate callbacks occur.
1302 [self removeWebViewAllowingCachedReconstruction:NO]; 1266 [self removeWebViewAllowingCachedReconstruction:NO];
1303 1267
1304 _webStateImpl = nullptr; 1268 _webStateImpl = nullptr;
1305 } 1269 }
1306 1270
1307 - (void)setDOMElementForLastTouch:(NSDictionary*)element {
1308 _DOMElementForLastTouch.reset([element copy]);
1309 }
1310
1311 - (void)showContextMenu:(UIGestureRecognizer*)gestureRecognizer {
1312 // We don't want ongoing notification that the long press is held.
1313 if ([gestureRecognizer state] != UIGestureRecognizerStateBegan)
1314 return;
1315
1316 if (![_DOMElementForLastTouch count])
1317 return;
1318
1319 web::ContextMenuParams params =
1320 [self contextMenuParamsForElement:_DOMElementForLastTouch.get()];
1321 params.view.reset([_webView retain]);
1322 params.location = [gestureRecognizer locationInView:_webView];
1323 if (self.webStateImpl->HandleContextMenu(params)) {
1324 // Cancelling all touches has the intended side effect of suppressing the
1325 // system's context menu.
1326 [self cancelAllTouches];
1327 }
1328 }
1329
1330 - (void)cancelAllTouches {
1331 // Disable web view scrolling.
1332 CancelTouches(self.webScrollView.panGestureRecognizer);
1333
1334 // All user gestures are handled by a subview of web view scroll view
1335 // (WKContentView).
1336 for (UIView* subview in self.webScrollView.subviews) {
1337 for (UIGestureRecognizer* recognizer in subview.gestureRecognizers) {
1338 CancelTouches(recognizer);
1339 }
1340 }
1341
1342 // Just disabling/enabling the gesture recognizers is not enough to suppress
1343 // the click handlers on the JS side. This JS performs the function of
1344 // suppressing these handlers on the JS side.
1345 NSString* suppressNextClick = @"__gCrWeb.suppressNextClick()";
1346 [self executeJavaScript:suppressNextClick completionHandler:nil];
1347 }
1348
1349 // TODO(shreyasv): This code is shared with SnapshotManager. Remove this and add 1271 // TODO(shreyasv): This code is shared with SnapshotManager. Remove this and add
1350 // it as part of WebDelegate delegate API such that a default image is returned 1272 // it as part of WebDelegate delegate API such that a default image is returned
1351 // immediately. 1273 // immediately.
1352 + (UIImage*)defaultSnapshotImage { 1274 + (UIImage*)defaultSnapshotImage {
1353 static UIImage* defaultImage = nil; 1275 static UIImage* defaultImage = nil;
1354 1276
1355 if (!defaultImage) { 1277 if (!defaultImage) {
1356 CGRect frame = CGRectMake(0, 0, 2, 2); 1278 CGRect frame = CGRectMake(0, 0, 2, 2);
1357 UIGraphicsBeginImageContext(frame.size); 1279 UIGraphicsBeginImageContext(frame.size);
1358 [[UIColor whiteColor] setFill]; 1280 [[UIColor whiteColor] setFill];
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1576 // Default value for shouldSuppressDialogs is NO, so updating them only 1498 // Default value for shouldSuppressDialogs is NO, so updating them only
1577 // when necessary is a good optimization. 1499 // when necessary is a good optimization.
1578 if (_shouldSuppressDialogsOnWindowIDInjection) { 1500 if (_shouldSuppressDialogsOnWindowIDInjection) {
1579 self.shouldSuppressDialogs = YES; 1501 self.shouldSuppressDialogs = YES;
1580 _shouldSuppressDialogsOnWindowIDInjection = NO; 1502 _shouldSuppressDialogsOnWindowIDInjection = NO;
1581 } 1503 }
1582 1504
1583 [_windowIDJSManager inject]; 1505 [_windowIDJSManager inject];
1584 } 1506 }
1585 1507
1586 // Set the specified recognizer to take priority over any recognizers in the
1587 // view that have a description containing the specified text fragment.
1588 + (void)requireGestureRecognizerToFail:(UIGestureRecognizer*)recognizer
1589 inView:(UIView*)view
1590 containingDescription:(NSString*)fragment {
1591 for (UIGestureRecognizer* iRecognizer in [view gestureRecognizers]) {
1592 if (iRecognizer != recognizer) {
1593 NSString* description = [iRecognizer description];
1594 if ([description rangeOfString:fragment].length) {
1595 [iRecognizer requireGestureRecognizerToFail:recognizer];
1596 // requireGestureRecognizerToFail: doesn't retain the recognizer, so it
1597 // is possible for |iRecognizer| to outlive |recognizer| and end up with
1598 // a dangling pointer. Add a retaining associative reference to ensure
1599 // that the lifetimes work out.
1600 // Note that normally using the value as the key wouldn't make any
1601 // sense, but here it's fine since nothing needs to look up the value.
1602 objc_setAssociatedObject(view, recognizer, recognizer,
1603 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1604 }
1605 }
1606 }
1607 }
1608
1609 - (CRWWebController*)createChildWebController { 1508 - (CRWWebController*)createChildWebController {
1610 CRWWebController* result = [self.delegate webPageOrderedOpen]; 1509 CRWWebController* result = [self.delegate webPageOrderedOpen];
1611 DCHECK(!result || result.sessionController.openedByDOM); 1510 DCHECK(!result || result.sessionController.openedByDOM);
1612 return result; 1511 return result;
1613 } 1512 }
1614 1513
1615 - (BOOL)canUseViewForGeneratingOverlayPlaceholderView { 1514 - (BOOL)canUseViewForGeneratingOverlayPlaceholderView {
1616 return _containerView != nil; 1515 return _containerView != nil;
1617 } 1516 }
1618 1517
(...skipping 1981 matching lines...) Expand 10 before | Expand all | Expand 10 after
3600 _webUIManager.reset( 3499 _webUIManager.reset(
3601 [[CRWWebUIManager alloc] initWithWebState:self.webStateImpl]); 3500 [[CRWWebUIManager alloc] initWithWebState:self.webStateImpl]);
3602 } 3501 }
3603 3502
3604 - (void)clearWebUI { 3503 - (void)clearWebUI {
3605 _webStateImpl->ClearWebUI(); 3504 _webStateImpl->ClearWebUI();
3606 _webUIManager.reset(); 3505 _webUIManager.reset();
3607 } 3506 }
3608 3507
3609 #pragma mark - 3508 #pragma mark -
3610 #pragma mark UIGestureRecognizerDelegate
3611
3612 - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
3613 shouldRecognizeSimultaneouslyWithGestureRecognizer:
3614 (UIGestureRecognizer*)otherGestureRecognizer {
3615 // Allows the custom UILongPressGestureRecognizer to fire simultaneously with
3616 // other recognizers.
3617 return YES;
3618 }
3619
3620 - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
3621 shouldReceiveTouch:(UITouch*)touch {
3622 // Expect only _contextMenuRecognizer.
3623 DCHECK([gestureRecognizer isEqual:_contextMenuRecognizer]);
3624
3625 // This is custom long press gesture recognizer. By the time the gesture is
3626 // recognized the web controller needs to know if there is a link under the
3627 // touch. If there a link, the web controller will reject system's context
3628 // menu and show another one. If for some reason context menu info is not
3629 // fetched - system context menu will be shown.
3630 [self setDOMElementForLastTouch:nil];
3631 base::WeakNSObject<CRWWebController> weakSelf(self);
3632 [self fetchDOMElementAtPoint:[touch locationInView:_webView]
3633 completionHandler:^(NSDictionary* element) {
3634 [weakSelf setDOMElementForLastTouch:element];
3635 }];
3636 return YES;
3637 }
3638
3639 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer {
3640 // Expect only _contextMenuRecognizer.
3641 DCHECK([gestureRecognizer isEqual:_contextMenuRecognizer]);
3642 if (!_webView) {
3643 // Show the context menu iff currently displaying a web view.
3644 // Do nothing for native views.
3645 return NO;
3646 }
3647
3648 // Fetching is considered as successful even if |_DOMElementForLastTouch| is
3649 // empty. However if |_DOMElementForLastTouch| is empty then custom context
3650 // menu should not be shown.
3651 UMA_HISTOGRAM_BOOLEAN("WebController.FetchContextMenuInfoAsyncSucceeded",
3652 !!_DOMElementForLastTouch);
3653 return [_DOMElementForLastTouch count];
3654 }
3655
3656 #pragma mark -
3657 #pragma mark CRWRequestTrackerDelegate 3509 #pragma mark CRWRequestTrackerDelegate
3658 3510
3659 - (BOOL)isForStaticFileRequests { 3511 - (BOOL)isForStaticFileRequests {
3660 return NO; 3512 return NO;
3661 } 3513 }
3662 3514
3663 - (void)updatedSSLStatus:(const web::SSLStatus&)sslStatus 3515 - (void)updatedSSLStatus:(const web::SSLStatus&)sslStatus
3664 forPageUrl:(const GURL&)url 3516 forPageUrl:(const GURL&)url
3665 userInfo:(id)userInfo { 3517 userInfo:(id)userInfo {
3666 // |userInfo| is a CRWSessionEntry. 3518 // |userInfo| is a CRWSessionEntry.
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
4310 // when the page finishes loading. 4162 // when the page finishes loading.
4311 base::WeakNSObject<UIScrollView> weakScrollView(self.webScrollView); 4163 base::WeakNSObject<UIScrollView> weakScrollView(self.webScrollView);
4312 base::scoped_nsprotocol<ProceduralBlock> action([^{ 4164 base::scoped_nsprotocol<ProceduralBlock> action([^{
4313 [weakScrollView setContentOffset:scrollOffset]; 4165 [weakScrollView setContentOffset:scrollOffset];
4314 } copy]); 4166 } copy]);
4315 [_pendingLoadCompleteActions addObject:action]; 4167 [_pendingLoadCompleteActions addObject:action];
4316 } 4168 }
4317 } 4169 }
4318 4170
4319 #pragma mark - 4171 #pragma mark -
4320 #pragma mark Web Page Features
4321
4322 - (void)fetchWebPageWidthWithCompletionHandler:(void (^)(CGFloat))handler {
4323 if (!_webView) {
4324 handler(0);
4325 return;
4326 }
4327
4328 [self executeJavaScript:@"__gCrWeb.getPageWidth();"
4329 completionHandler:^(id pageWidth, NSError*) {
4330 handler([base::mac::ObjCCastStrict<NSNumber>(pageWidth) floatValue]);
4331 }];
4332 }
4333
4334 - (void)fetchDOMElementAtPoint:(CGPoint)point
4335 completionHandler:(void (^)(NSDictionary*))handler {
4336 DCHECK(handler);
4337 // Convert point into web page's coordinate system (which may be scaled and/or
4338 // scrolled).
4339 CGPoint scrollOffset = self.scrollPosition;
4340 CGFloat webViewContentWidth = self.webScrollView.contentSize.width;
4341 base::WeakNSObject<CRWWebController> weakSelf(self);
4342 [self fetchWebPageWidthWithCompletionHandler:^(CGFloat pageWidth) {
4343 CGFloat scale = pageWidth / webViewContentWidth;
4344 CGPoint localPoint = CGPointMake((point.x + scrollOffset.x) * scale,
4345 (point.y + scrollOffset.y) * scale);
4346 NSString* const kGetElementScript =
4347 [NSString stringWithFormat:@"__gCrWeb.getElementFromPoint(%g, %g);",
4348 localPoint.x, localPoint.y];
4349 [weakSelf executeJavaScript:kGetElementScript
4350 completionHandler:^(id element, NSError*) {
4351 handler(base::mac::ObjCCastStrict<NSDictionary>(element));
4352 }];
4353 }];
4354 }
4355
4356 - (web::ContextMenuParams)contextMenuParamsForElement:(NSDictionary*)element {
4357 web::ContextMenuParams params;
4358 NSString* title = nil;
4359 NSString* href = element[@"href"];
4360 if (href) {
4361 params.link_url = GURL(base::SysNSStringToUTF8(href));
4362 if (params.link_url.SchemeIs(url::kJavaScriptScheme)) {
4363 title = @"JavaScript";
4364 } else {
4365 base::string16 URLText = url_formatter::FormatUrl(params.link_url);
4366 title = base::SysUTF16ToNSString(URLText);
4367 }
4368 }
4369 NSString* src = element[@"src"];
4370 if (src) {
4371 params.src_url = GURL(base::SysNSStringToUTF8(src));
4372 if (!title)
4373 title = [[src copy] autorelease];
4374 if ([title hasPrefix:base::SysUTF8ToNSString(url::kDataScheme)])
4375 title = nil;
4376 }
4377 NSString* titleAttribute = element[@"title"];
4378 if (titleAttribute)
4379 title = titleAttribute;
4380 if (title) {
4381 params.menu_title.reset([title copy]);
4382 }
4383 NSString* referrerPolicy = element[@"referrerPolicy"];
4384 if (referrerPolicy) {
4385 params.referrer_policy =
4386 web::ReferrerPolicyFromString(base::SysNSStringToUTF8(referrerPolicy));
4387 }
4388 NSString* innerText = element[@"innerText"];
4389 if ([innerText length] > 0) {
4390 params.link_text.reset([innerText copy]);
4391 }
4392 return params;
4393 }
4394
4395 #pragma mark -
4396 #pragma mark Fullscreen 4172 #pragma mark Fullscreen
4397 4173
4398 - (CGRect)visibleFrame { 4174 - (CGRect)visibleFrame {
4399 CGRect frame = [_containerView bounds]; 4175 CGRect frame = [_containerView bounds];
4400 CGFloat headerHeight = [self headerHeight]; 4176 CGFloat headerHeight = [self headerHeight];
4401 frame.origin.y = headerHeight; 4177 frame.origin.y = headerHeight;
4402 frame.size.height -= headerHeight; 4178 frame.size.height -= headerHeight;
4403 return frame; 4179 return frame;
4404 } 4180 }
4405 4181
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
4668 // Create a dependency between the |webView| pan gesture and BVC side swipe 4444 // Create a dependency between the |webView| pan gesture and BVC side swipe
4669 // gestures. Note: This needs to be added before the longPress recognizers 4445 // gestures. Note: This needs to be added before the longPress recognizers
4670 // below, or the longPress appears to deadlock the remaining recognizers, 4446 // below, or the longPress appears to deadlock the remaining recognizers,
4671 // thereby breaking scroll. 4447 // thereby breaking scroll.
4672 NSSet* recognizers = [_swipeRecognizerProvider swipeRecognizers]; 4448 NSSet* recognizers = [_swipeRecognizerProvider swipeRecognizers];
4673 for (UISwipeGestureRecognizer* swipeRecognizer in recognizers) { 4449 for (UISwipeGestureRecognizer* swipeRecognizer in recognizers) {
4674 [self.webScrollView.panGestureRecognizer 4450 [self.webScrollView.panGestureRecognizer
4675 requireGestureRecognizerToFail:swipeRecognizer]; 4451 requireGestureRecognizerToFail:swipeRecognizer];
4676 } 4452 }
4677 4453
4678 // On iOS 4.x, there are two gesture recognizers on the UIWebView 4454 _contextMenuController.reset([[CRWContextMenuController alloc]
4679 // subclasses, 4455 initWithWebView:_webView
4680 // that have a minimum tap threshold of 0.12s and 0.75s. 4456 javaScriptDelegate:self
4681 // 4457 delegate:self]);
4682 // My theory is that the shorter threshold recognizer performs the link
4683 // highlight (grey highlight around links when it is tapped and held) while
4684 // the longer threshold one pops up the context menu.
4685 //
4686 // To override the context menu, this recognizer needs to react faster than
4687 // the 0.75s one. The below gesture recognizer is initialized with a
4688 // detection duration a little lower than that (see
4689 // kLongPressDurationSeconds). It also points the delegate to this class
4690 // that
4691 // allows simultaneously operate along with the other recognizers.
4692 _contextMenuRecognizer.reset([[UILongPressGestureRecognizer alloc]
4693 initWithTarget:self
4694 action:@selector(showContextMenu:)]);
4695 [_contextMenuRecognizer setMinimumPressDuration:kLongPressDurationSeconds];
4696 [_contextMenuRecognizer setAllowableMovement:kLongPressMoveDeltaPixels];
4697 [_contextMenuRecognizer setDelegate:self];
4698 [_webView addGestureRecognizer:_contextMenuRecognizer];
4699 // Certain system gesture handlers are known to conflict with our context
4700 // menu handler, causing extra events to fire when the context menu is
4701 // active.
4702
4703 // A number of solutions have been investigated. The lowest-risk solution
4704 // appears to be to recurse through the web controller's recognizers,
4705 // looking
4706 // for fingerprints of the recognizers known to cause problems, which are
4707 // then
4708 // de-prioritized (below our own long click handler).
4709 // Hunting for description fragments of system recognizers is undeniably
4710 // brittle for future versions of iOS. If it does break the context menu
4711 // events may leak (regressing b/5310177), but the app will otherwise work.
4712 [CRWWebController requireGestureRecognizerToFail:_contextMenuRecognizer
4713 inView:_webView
4714 containingDescription:
4715 @"action=_highlightLongPressRecognized:"];
4716 4458
4717 // Add all additional gesture recognizers to the web view. 4459 // Add all additional gesture recognizers to the web view.
4718 for (UIGestureRecognizer* recognizer in _gestureRecognizers.get()) { 4460 for (UIGestureRecognizer* recognizer in _gestureRecognizers.get()) {
4719 [_webView addGestureRecognizer:recognizer]; 4461 [_webView addGestureRecognizer:recognizer];
4720 } 4462 }
4721 4463
4722 _URLOnStartLoading = _defaultURL; 4464 _URLOnStartLoading = _defaultURL;
4723 4465
4724 // Add the web toolbars. 4466 // Add the web toolbars.
4725 [_containerView addToolbars:_webViewToolbars]; 4467 [_containerView addToolbars:_webViewToolbars];
4726 4468
4727 base::scoped_nsobject<CRWWebViewContentView> webViewContentView( 4469 base::scoped_nsobject<CRWWebViewContentView> webViewContentView(
4728 [[CRWWebViewContentView alloc] initWithWebView:_webView 4470 [[CRWWebViewContentView alloc] initWithWebView:_webView
4729 scrollView:self.webScrollView]); 4471 scrollView:self.webScrollView]);
4730 [_containerView displayWebViewContentView:webViewContentView]; 4472 [_containerView displayWebViewContentView:webViewContentView];
4731 } 4473 }
4732 } 4474 }
4733 4475
4734 - (WKWebView*)webViewWithConfiguration:(WKWebViewConfiguration*)config { 4476 - (WKWebView*)webViewWithConfiguration:(WKWebViewConfiguration*)config {
4477 // Do not attach the context menu controller immediately as the JavaScript
4478 // delegate must be specified.
4735 return web::BuildWKWebView(CGRectZero, config, 4479 return web::BuildWKWebView(CGRectZero, config,
4736 self.webStateImpl->GetBrowserState(), 4480 self.webStateImpl->GetBrowserState(),
4737 [self useDesktopUserAgent]); 4481 [self useDesktopUserAgent]);
4738 } 4482 }
4739 4483
4740 - (void)setWebView:(WKWebView*)webView { 4484 - (void)setWebView:(WKWebView*)webView {
4741 DCHECK_NE(_webView.get(), webView); 4485 DCHECK_NE(_webView.get(), webView);
4742 4486
4743 // Unwind the old web view. 4487 // Unwind the old web view.
4744 // TODO(eugenebut): Remove CRWWKScriptMessageRouter once crbug.com/543374 is 4488 // TODO(eugenebut): Remove CRWWKScriptMessageRouter once crbug.com/543374 is
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
5359 - (void)SSLStatusUpdater:(CRWSSLStatusUpdater*)SSLStatusUpdater 5103 - (void)SSLStatusUpdater:(CRWSSLStatusUpdater*)SSLStatusUpdater
5360 didChangeSSLStatusForNavigationItem:(web::NavigationItem*)navigationItem { 5104 didChangeSSLStatusForNavigationItem:(web::NavigationItem*)navigationItem {
5361 web::NavigationItem* currentNavigationItem = 5105 web::NavigationItem* currentNavigationItem =
5362 self.webState->GetNavigationManager()->GetLastCommittedItem(); 5106 self.webState->GetNavigationManager()->GetLastCommittedItem();
5363 if (navigationItem == currentNavigationItem) { 5107 if (navigationItem == currentNavigationItem) {
5364 [self didUpdateSSLStatusForCurrentNavigationItem]; 5108 [self didUpdateSSLStatusForCurrentNavigationItem];
5365 } 5109 }
5366 } 5110 }
5367 5111
5368 #pragma mark - 5112 #pragma mark -
5113 #pragma mark CRWWebContextMenuControllerDelegate methods
5114
5115 - (BOOL)webView:(WKWebView*)webView
5116 handleContextMenu:(const web::ContextMenuParams&)params {
5117 DCHECK(webView == _webView);
5118 return self.webStateImpl->HandleContextMenu(params);
Eugene But (OOO till 7-30) 2017/01/13 16:19:42 This can be called asynchronously, when WebState i
Olivier 2017/01/13 18:08:59 Done.
5119 }
5120
5121 #pragma mark -
5122 #pragma mark CRWNativeContentDelegate methods
Eugene But (OOO till 7-30) 2017/01/13 16:19:42 nit: Add a linebreak
Olivier 2017/01/13 18:08:59 Done.
5123 - (BOOL)nativeContent:(id)content
5124 handleContextMenu:(const web::ContextMenuParams&)params {
5125 return self.webStateImpl->HandleContextMenu(params);
Eugene But (OOO till 7-30) 2017/01/13 16:19:42 Please check _isBeingDestroyed
Olivier 2017/01/13 18:08:59 Done.
5126 }
5127
5128 #pragma mark -
5369 #pragma mark KVO Observation 5129 #pragma mark KVO Observation
5370 5130
5371 - (void)observeValueForKeyPath:(NSString*)keyPath 5131 - (void)observeValueForKeyPath:(NSString*)keyPath
5372 ofObject:(id)object 5132 ofObject:(id)object
5373 change:(NSDictionary*)change 5133 change:(NSDictionary*)change
5374 context:(void*)context { 5134 context:(void*)context {
5375 NSString* dispatcherSelectorName = self.WKWebViewObservers[keyPath]; 5135 NSString* dispatcherSelectorName = self.WKWebViewObservers[keyPath];
5376 DCHECK(dispatcherSelectorName); 5136 DCHECK(dispatcherSelectorName);
5377 if (dispatcherSelectorName) 5137 if (dispatcherSelectorName)
5378 [self performSelector:NSSelectorFromString(dispatcherSelectorName)]; 5138 [self performSelector:NSSelectorFromString(dispatcherSelectorName)];
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
5768 } 5528 }
5769 5529
5770 return web::WEB_VIEW_DOCUMENT_TYPE_GENERIC; 5530 return web::WEB_VIEW_DOCUMENT_TYPE_GENERIC;
5771 } 5531 }
5772 5532
5773 - (NSString*)refererFromNavigationAction:(WKNavigationAction*)action { 5533 - (NSString*)refererFromNavigationAction:(WKNavigationAction*)action {
5774 return [action.request valueForHTTPHeaderField:@"Referer"]; 5534 return [action.request valueForHTTPHeaderField:@"Referer"];
5775 } 5535 }
5776 5536
5777 @end 5537 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698