Chromium Code Reviews

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

Issue 2821173002: Handle correctly start and commit of non-latest navigations. (Closed)
Patch Set: Fixed eg tests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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 598 matching lines...)
609 // Updates the internal state and informs the delegate that any outstanding load 609 // Updates the internal state and informs the delegate that any outstanding load
610 // operations are cancelled. 610 // operations are cancelled.
611 - (void)loadCancelled; 611 - (void)loadCancelled;
612 // If YES, the page should be closed if it successfully redirects to a native 612 // If YES, the page should be closed if it successfully redirects to a native
613 // application, for example if a new tab redirects to the App Store. 613 // application, for example if a new tab redirects to the App Store.
614 - (BOOL)shouldClosePageOnNativeApplicationLoad; 614 - (BOOL)shouldClosePageOnNativeApplicationLoad;
615 // Called following navigation completion to generate final navigation lifecycle 615 // Called following navigation completion to generate final navigation lifecycle
616 // events. Navigation is considered complete when the document has finished 616 // events. Navigation is considered complete when the document has finished
617 // loading, or when other page load mechanics are completed on a 617 // loading, or when other page load mechanics are completed on a
618 // non-document-changing URL change. 618 // non-document-changing URL change.
619 - (void)didFinishNavigation; 619 - (void)didFinishNavigation:(WKNavigation*)navigation;
620 // Update the appropriate parts of the model and broadcast to the embedder. This 620 // Update the appropriate parts of the model and broadcast to the embedder. This
621 // may be called multiple times and thus must be idempotent. 621 // may be called multiple times and thus must be idempotent.
622 - (void)loadCompleteWithSuccess:(BOOL)loadSuccess; 622 - (void)loadCompleteWithSuccess:(BOOL)loadSuccess
623 forNavigation:(WKNavigation*)navigation;
623 // Called after URL is finished loading and _loadPhase is set to PAGE_LOADED. 624 // Called after URL is finished loading and _loadPhase is set to PAGE_LOADED.
624 - (void)didFinishWithURL:(const GURL&)currentURL loadSuccess:(BOOL)loadSuccess; 625 - (void)didFinishWithURL:(const GURL&)currentURL loadSuccess:(BOOL)loadSuccess;
625 // Navigates forwards or backwards by |delta| pages. No-op if delta is out of 626 // Navigates forwards or backwards by |delta| pages. No-op if delta is out of
626 // bounds. Reloads if delta is 0. 627 // bounds. Reloads if delta is 0.
627 // TODO(crbug.com/661316): Move this method to NavigationManager. 628 // TODO(crbug.com/661316): Move this method to NavigationManager.
628 - (void)goDelta:(int)delta; 629 - (void)goDelta:(int)delta;
629 // Informs the native controller if web usage is allowed or not. 630 // Informs the native controller if web usage is allowed or not.
630 - (void)setNativeControllerWebUsageEnabled:(BOOL)webUsageEnabled; 631 - (void)setNativeControllerWebUsageEnabled:(BOOL)webUsageEnabled;
631 // Called when web controller receives a new message from the web page. 632 // Called when web controller receives a new message from the web page.
632 - (void)didReceiveScriptMessage:(WKScriptMessage*)message; 633 - (void)didReceiveScriptMessage:(WKScriptMessage*)message;
(...skipping 116 matching lines...)
749 sourceURL:(const GURL&)sourceURL 750 sourceURL:(const GURL&)sourceURL
750 linkActivatedNavigation:(BOOL)linkActivatedNavigation; 751 linkActivatedNavigation:(BOOL)linkActivatedNavigation;
751 // Returns YES if the navigation action is associated with a main frame request. 752 // Returns YES if the navigation action is associated with a main frame request.
752 - (BOOL)isMainFrameNavigationAction:(WKNavigationAction*)action; 753 - (BOOL)isMainFrameNavigationAction:(WKNavigationAction*)action;
753 // Returns whether external URL navigation action should be opened. 754 // Returns whether external URL navigation action should be opened.
754 - (BOOL)shouldOpenExternalURLForNavigationAction:(WKNavigationAction*)action; 755 - (BOOL)shouldOpenExternalURLForNavigationAction:(WKNavigationAction*)action;
755 // Updates SSL status for the current navigation item based on the information 756 // Updates SSL status for the current navigation item based on the information
756 // provided by web view. 757 // provided by web view.
757 - (void)updateSSLStatusForCurrentNavigationItem; 758 - (void)updateSSLStatusForCurrentNavigationItem;
758 // Called when a load ends in an SSL error and certificate chain. 759 // Called when a load ends in an SSL error and certificate chain.
759 - (void)handleSSLCertError:(NSError*)error; 760 - (void)handleSSLCertError:(NSError*)error forNavigation:navigation;
760 761
761 // Used in webView:didReceiveAuthenticationChallenge:completionHandler: to 762 // Used in webView:didReceiveAuthenticationChallenge:completionHandler: to
762 // reply with NSURLSessionAuthChallengeDisposition and credentials. 763 // reply with NSURLSessionAuthChallengeDisposition and credentials.
763 - (void)processAuthChallenge:(NSURLAuthenticationChallenge*)challenge 764 - (void)processAuthChallenge:(NSURLAuthenticationChallenge*)challenge
764 forCertAcceptPolicy:(web::CertAcceptPolicy)policy 765 forCertAcceptPolicy:(web::CertAcceptPolicy)policy
765 certStatus:(net::CertStatus)certStatus 766 certStatus:(net::CertStatus)certStatus
766 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, 767 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition,
767 NSURLCredential*))completionHandler; 768 NSURLCredential*))completionHandler;
768 // Used in webView:didReceiveAuthenticationChallenge:completionHandler: to reply 769 // Used in webView:didReceiveAuthenticationChallenge:completionHandler: to reply
769 // with NSURLSessionAuthChallengeDisposition and credentials. 770 // with NSURLSessionAuthChallengeDisposition and credentials.
(...skipping 112 matching lines...)
882 (base::DictionaryValue*)message 883 (base::DictionaryValue*)message
883 context:(NSDictionary*)context; 884 context:(NSDictionary*)context;
884 885
885 // Returns YES if the given |action| should be allowed to continue. 886 // Returns YES if the given |action| should be allowed to continue.
886 // If this returns NO, the load should be cancelled. 887 // If this returns NO, the load should be cancelled.
887 - (BOOL)shouldAllowLoadWithNavigationAction:(WKNavigationAction*)action; 888 - (BOOL)shouldAllowLoadWithNavigationAction:(WKNavigationAction*)action;
888 // Called when a load ends in an error. 889 // Called when a load ends in an error.
889 // TODO(stuartmorgan): Figure out if there's actually enough shared logic that 890 // TODO(stuartmorgan): Figure out if there's actually enough shared logic that
890 // this makes sense. At the very least remove inMainFrame since that only makes 891 // this makes sense. At the very least remove inMainFrame since that only makes
891 // sense for UIWebView. 892 // sense for UIWebView.
892 - (void)handleLoadError:(NSError*)error inMainFrame:(BOOL)inMainFrame; 893 - (void)handleLoadError:(NSError*)error
894 inMainFrame:(BOOL)inMainFrame
895 forNavigation:(WKNavigation*)navigation;
893 896
894 // Handles cancelled load in WKWebView (error with NSURLErrorCancelled code). 897 // Handles cancelled load in WKWebView (error with NSURLErrorCancelled code).
895 - (void)handleCancelledError:(NSError*)error; 898 - (void)handleCancelledError:(NSError*)error;
896 899
897 // Used to decide whether a load that generates errors with the 900 // Used to decide whether a load that generates errors with the
898 // NSURLErrorCancelled code should be cancelled. 901 // NSURLErrorCancelled code should be cancelled.
899 - (BOOL)shouldCancelLoadForCancelledError:(NSError*)error; 902 - (BOOL)shouldCancelLoadForCancelledError:(NSError*)error;
900 903
901 // Sets up WebUI for URL. 904 // Sets up WebUI for URL.
902 - (void)createWebUIForURL:(const GURL&)URL; 905 - (void)createWebUIForURL:(const GURL&)URL;
(...skipping 1160 matching lines...)
2063 2066
2064 // Update the user agent before attempting the navigation. 2067 // Update the user agent before attempting the navigation.
2065 web::NavigationItem* toItem = items[index].get(); 2068 web::NavigationItem* toItem = items[index].get();
2066 [self updateWebViewUserAgentFromUserAgentType:toItem->GetUserAgentType()]; 2069 [self updateWebViewUserAgentFromUserAgentType:toItem->GetUserAgentType()];
2067 2070
2068 web::NavigationItem* fromItem = sessionController.currentItem; 2071 web::NavigationItem* fromItem = sessionController.currentItem;
2069 BOOL sameDocumentNavigation = 2072 BOOL sameDocumentNavigation =
2070 [sessionController isSameDocumentNavigationBetweenItem:fromItem 2073 [sessionController isSameDocumentNavigationBetweenItem:fromItem
2071 andItem:toItem]; 2074 andItem:toItem];
2072 if (sameDocumentNavigation) { 2075 if (sameDocumentNavigation) {
2073 [sessionController goToItemAtIndex:index]; 2076 [sessionController goToItemAtIndex:index discardNonCommittedItems:YES];
2074 [self updateHTML5HistoryState]; 2077 [self updateHTML5HistoryState];
2075 } else { 2078 } else {
2076 [sessionController discardNonCommittedItems]; 2079 [sessionController discardNonCommittedItems];
2077 [sessionController setPendingItemIndex:index]; 2080 [sessionController setPendingItemIndex:index];
2078 2081
2079 web::NavigationItemImpl* pendingItem = sessionController.pendingItem; 2082 web::NavigationItemImpl* pendingItem = sessionController.pendingItem;
2080 pendingItem->SetTransitionType(ui::PageTransitionFromInt( 2083 pendingItem->SetTransitionType(ui::PageTransitionFromInt(
2081 pendingItem->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK)); 2084 pendingItem->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK));
2082 2085
2083 [self loadCurrentURL]; 2086 [self loadCurrentURL];
2084 } 2087 }
2085 } 2088 }
2086 2089
2087 - (BOOL)isLoaded { 2090 - (BOOL)isLoaded {
2088 return _loadPhase == web::PAGE_LOADED; 2091 return _loadPhase == web::PAGE_LOADED;
2089 } 2092 }
2090 2093
2091 - (void)didFinishNavigation { 2094 - (void)didFinishNavigation:(WKNavigation*)navigation {
2092 // This can be called at multiple times after the document has loaded. Do 2095 // This can be called at multiple times after the document has loaded. Do
2093 // nothing if the document has already loaded. 2096 // nothing if the document has already loaded.
2094 if (_loadPhase == web::PAGE_LOADED) 2097 if (_loadPhase == web::PAGE_LOADED)
2095 return; 2098 return;
2096 [self loadCompleteWithSuccess:YES]; 2099 [self loadCompleteWithSuccess:YES forNavigation:navigation];
2097 } 2100 }
2098 2101
2099 - (void)loadCompleteWithSuccess:(BOOL)loadSuccess { 2102 - (void)loadCompleteWithSuccess:(BOOL)loadSuccess
2103 forNavigation:(WKNavigation*)navigation {
2100 [self removePlaceholderOverlay]; 2104 [self removePlaceholderOverlay];
2101 // The webView may have been torn down (or replaced by a native view). Be 2105 // The webView may have been torn down (or replaced by a native view). Be
2102 // safe and do nothing if that's happened. 2106 // safe and do nothing if that's happened.
2103 if (_loadPhase != web::PAGE_LOADING) 2107 if (_loadPhase != web::PAGE_LOADING)
2104 return; 2108 return;
2105 2109
2106 DCHECK(_webView); 2110 DCHECK(_webView);
2107 2111
2108 const GURL currentURL([self currentURL]); 2112 const GURL currentURL([self currentURL]);
2109 2113
2110 _loadPhase = web::PAGE_LOADED; 2114 _loadPhase = web::PAGE_LOADED;
2111 2115
2112 [self optOutScrollsToTopForSubviews]; 2116 [self optOutScrollsToTopForSubviews];
2113 2117
2114 // Ensure the URL is as expected (and already reported to the delegate). 2118 DCHECK((currentURL == _lastRegisteredRequestURL) || // latest navigation
2115 // If |_lastRegisteredRequestURL| is invalid then |currentURL| will be 2119 // previous navigation
2116 // "about:blank". 2120 ![[_navigationStates lastAddedNavigation] isEqual:navigation] ||
2117 DCHECK((currentURL == _lastRegisteredRequestURL) ||
2118 (!_lastRegisteredRequestURL.is_valid() && 2121 (!_lastRegisteredRequestURL.is_valid() &&
2119 _documentURL.spec() == url::kAboutBlankURL)) 2122 _documentURL.spec() == url::kAboutBlankURL) /* invalid URL load */)
kkhorimoto 2017/04/18 23:03:15 Some of these are line comments, but some are bloc
Eugene But (OOO till 7-30) 2017/04/19 00:26:46 Done.
2120 << std::endl 2123 << std::endl
2121 << "currentURL = [" << currentURL << "]" << std::endl 2124 << "currentURL = [" << currentURL << "]" << std::endl
2122 << "_lastRegisteredRequestURL = [" << _lastRegisteredRequestURL << "]"; 2125 << "_lastRegisteredRequestURL = [" << _lastRegisteredRequestURL << "]";
2123 2126
2124 // Perform post-load-finished updates. 2127 // Perform post-load-finished updates.
2125 [self didFinishWithURL:currentURL loadSuccess:loadSuccess]; 2128 [self didFinishWithURL:currentURL loadSuccess:loadSuccess];
2126 2129
2127 // Execute the pending LoadCompleteActions. 2130 // Execute the pending LoadCompleteActions.
2128 for (ProceduralBlock action in _pendingLoadCompleteActions.get()) { 2131 for (ProceduralBlock action in _pendingLoadCompleteActions.get()) {
2129 action(); 2132 action();
(...skipping 686 matching lines...)
2816 transition:transition]; 2819 transition:transition];
2817 2820
2818 NSString* replaceWebViewJS = 2821 NSString* replaceWebViewJS =
2819 [self javaScriptToReplaceWebViewURL:pushURL stateObjectJSON:stateObject]; 2822 [self javaScriptToReplaceWebViewURL:pushURL stateObjectJSON:stateObject];
2820 base::WeakNSObject<CRWWebController> weakSelf(self); 2823 base::WeakNSObject<CRWWebController> weakSelf(self);
2821 [self executeJavaScript:replaceWebViewJS completionHandler:^(id, NSError*) { 2824 [self executeJavaScript:replaceWebViewJS completionHandler:^(id, NSError*) {
2822 if (!weakSelf || weakSelf.get()->_isBeingDestroyed) 2825 if (!weakSelf || weakSelf.get()->_isBeingDestroyed)
2823 return; 2826 return;
2824 base::scoped_nsobject<CRWWebController> strongSelf([weakSelf retain]); 2827 base::scoped_nsobject<CRWWebController> strongSelf([weakSelf retain]);
2825 [strongSelf optOutScrollsToTopForSubviews]; 2828 [strongSelf optOutScrollsToTopForSubviews];
2826 [strongSelf didFinishNavigation]; 2829 [strongSelf didFinishNavigation:nil];
2827 }]; 2830 }];
2828 return YES; 2831 return YES;
2829 } 2832 }
2830 2833
2831 - (BOOL)handleWindowHistoryDidReplaceStateMessage: 2834 - (BOOL)handleWindowHistoryDidReplaceStateMessage:
2832 (base::DictionaryValue*)message 2835 (base::DictionaryValue*)message
2833 context:(NSDictionary*)context { 2836 context:(NSDictionary*)context {
2834 DCHECK(_changingHistoryState); 2837 DCHECK(_changingHistoryState);
2835 _changingHistoryState = NO; 2838 _changingHistoryState = NO;
2836 2839
(...skipping 34 matching lines...)
2871 _URLOnStartLoading = replaceURL; 2874 _URLOnStartLoading = replaceURL;
2872 _lastRegisteredRequestURL = replaceURL; 2875 _lastRegisteredRequestURL = replaceURL;
2873 [self replaceStateWithPageURL:replaceURL stateObject:stateObject]; 2876 [self replaceStateWithPageURL:replaceURL stateObject:stateObject];
2874 NSString* replaceStateJS = [self javaScriptToReplaceWebViewURL:replaceURL 2877 NSString* replaceStateJS = [self javaScriptToReplaceWebViewURL:replaceURL
2875 stateObjectJSON:stateObject]; 2878 stateObjectJSON:stateObject];
2876 base::WeakNSObject<CRWWebController> weakSelf(self); 2879 base::WeakNSObject<CRWWebController> weakSelf(self);
2877 [self executeJavaScript:replaceStateJS completionHandler:^(id, NSError*) { 2880 [self executeJavaScript:replaceStateJS completionHandler:^(id, NSError*) {
2878 if (!weakSelf || weakSelf.get()->_isBeingDestroyed) 2881 if (!weakSelf || weakSelf.get()->_isBeingDestroyed)
2879 return; 2882 return;
2880 base::scoped_nsobject<CRWWebController> strongSelf([weakSelf retain]); 2883 base::scoped_nsobject<CRWWebController> strongSelf([weakSelf retain]);
2881 [strongSelf didFinishNavigation]; 2884 [strongSelf didFinishNavigation:nil];
2882 }]; 2885 }];
2883 return YES; 2886 return YES;
2884 } 2887 }
2885 2888
2886 #pragma mark - 2889 #pragma mark -
2887 2890
2888 - (BOOL)wantsKeyboardShield { 2891 - (BOOL)wantsKeyboardShield {
2889 if ([self.nativeController 2892 if ([self.nativeController
2890 respondsToSelector:@selector(wantsKeyboardShield)]) { 2893 respondsToSelector:@selector(wantsKeyboardShield)]) {
2891 return [self.nativeController wantsKeyboardShield]; 2894 return [self.nativeController wantsKeyboardShield];
(...skipping 214 matching lines...)
3106 web::NavigationItemImpl* item = self.currentNavItem; 3109 web::NavigationItemImpl* item = self.currentNavItem;
3107 // TODO(crbug.com/570699): Remove this check once it's no longer possible to 3110 // TODO(crbug.com/570699): Remove this check once it's no longer possible to
3108 // have no current entries. 3111 // have no current entries.
3109 if (item) 3112 if (item)
3110 [self cachePOSTDataForRequest:request inNavigationItem:item]; 3113 [self cachePOSTDataForRequest:request inNavigationItem:item];
3111 } 3114 }
3112 3115
3113 return YES; 3116 return YES;
3114 } 3117 }
3115 3118
3116 - (void)handleLoadError:(NSError*)error inMainFrame:(BOOL)inMainFrame { 3119 - (void)handleLoadError:(NSError*)error
3120 inMainFrame:(BOOL)inMainFrame
3121 forNavigation:(WKNavigation*)navigation {
3117 NSString* MIMEType = [_pendingNavigationInfo MIMEType]; 3122 NSString* MIMEType = [_pendingNavigationInfo MIMEType];
3118 if ([_passKitDownloader isMIMETypePassKitType:MIMEType]) 3123 if ([_passKitDownloader isMIMETypePassKitType:MIMEType])
3119 return; 3124 return;
3120 if ([error code] == NSURLErrorUnsupportedURL) 3125 if ([error code] == NSURLErrorUnsupportedURL)
3121 return; 3126 return;
3122 // In cases where a Plug-in handles the load do not take any further action. 3127 // In cases where a Plug-in handles the load do not take any further action.
3123 if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] && 3128 if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] &&
3124 (error.code == web::kWebKitErrorPlugInLoadFailed || 3129 (error.code == web::kWebKitErrorPlugInLoadFailed ||
3125 error.code == web::kWebKitErrorCannotShowUrl)) 3130 error.code == web::kWebKitErrorCannotShowUrl))
3126 return; 3131 return;
(...skipping 42 matching lines...)
3169 if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] && 3174 if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] &&
3170 error.code == web::kWebKitErrorFrameLoadInterruptedByPolicyChange) { 3175 error.code == web::kWebKitErrorFrameLoadInterruptedByPolicyChange) {
3171 // See if the delegate wants to handle this case. 3176 // See if the delegate wants to handle this case.
3172 if (errorGURL.is_valid() && 3177 if (errorGURL.is_valid() &&
3173 [_delegate 3178 [_delegate
3174 respondsToSelector:@selector( 3179 respondsToSelector:@selector(
3175 controllerForUnhandledContentAtURL:)]) { 3180 controllerForUnhandledContentAtURL:)]) {
3176 id<CRWNativeContent> controller = 3181 id<CRWNativeContent> controller =
3177 [_delegate controllerForUnhandledContentAtURL:errorGURL]; 3182 [_delegate controllerForUnhandledContentAtURL:errorGURL];
3178 if (controller) { 3183 if (controller) {
3179 [self loadCompleteWithSuccess:NO]; 3184 [self loadCompleteWithSuccess:NO forNavigation:navigation];
3180 [self removeWebViewAllowingCachedReconstruction:NO]; 3185 [self removeWebViewAllowingCachedReconstruction:NO];
3181 [self setNativeController:controller]; 3186 [self setNativeController:controller];
3182 [self loadNativeViewWithSuccess:YES]; 3187 [self loadNativeViewWithSuccess:YES];
3183 return; 3188 return;
3184 } 3189 }
3185 } 3190 }
3186 3191
3187 // Ignore errors that originate from URLs that are opened in external apps. 3192 // Ignore errors that originate from URLs that are opened in external apps.
3188 if ([_openedApplicationURL containsObject:errorURL]) 3193 if ([_openedApplicationURL containsObject:errorURL])
3189 return; 3194 return;
3190 // Certain frame errors don't have URL information for some reason; for 3195 // Certain frame errors don't have URL information for some reason; for
3191 // those cases (so far the only known case is plugin content loaded directly 3196 // those cases (so far the only known case is plugin content loaded directly
3192 // in a frame) just ignore the error. See crbug.com/414295 3197 // in a frame) just ignore the error. See crbug.com/414295
3193 if (!errorURL) { 3198 if (!errorURL) {
3194 DCHECK(!inMainFrame); 3199 DCHECK(!inMainFrame);
3195 return; 3200 return;
3196 } 3201 }
3197 // The wrapper error uses the URL of the error and not the requested URL 3202 // The wrapper error uses the URL of the error and not the requested URL
3198 // (which can be different in case of a redirect) to match desktop Chrome 3203 // (which can be different in case of a redirect) to match desktop Chrome
3199 // behavior. 3204 // behavior.
3200 NSError* wrapperError = [NSError 3205 NSError* wrapperError = [NSError
3201 errorWithDomain:[error domain] 3206 errorWithDomain:[error domain]
3202 code:[error code] 3207 code:[error code]
3203 userInfo:@{ 3208 userInfo:@{
3204 NSURLErrorFailingURLStringErrorKey : [errorURL absoluteString], 3209 NSURLErrorFailingURLStringErrorKey : [errorURL absoluteString],
3205 NSUnderlyingErrorKey : error 3210 NSUnderlyingErrorKey : error
3206 }]; 3211 }];
3207 [self loadCompleteWithSuccess:NO]; 3212 [self loadCompleteWithSuccess:NO forNavigation:navigation];
3208 [self loadErrorInNativeView:wrapperError]; 3213 [self loadErrorInNativeView:wrapperError];
3209 return; 3214 return;
3210 } 3215 }
3211 3216
3212 if ([error code] == NSURLErrorCancelled) { 3217 if ([error code] == NSURLErrorCancelled) {
3213 [self handleCancelledError:error]; 3218 [self handleCancelledError:error];
3214 // NSURLErrorCancelled errors that aren't handled by aborting the load will 3219 // NSURLErrorCancelled errors that aren't handled by aborting the load will
3215 // automatically be retried by the web view, so early return in this case. 3220 // automatically be retried by the web view, so early return in this case.
3216 return; 3221 return;
3217 } 3222 }
3218 3223
3219 [self loadCompleteWithSuccess:NO]; 3224 [self loadCompleteWithSuccess:NO forNavigation:navigation];
3220 [self loadErrorInNativeView:error]; 3225 [self loadErrorInNativeView:error];
3221 } 3226 }
3222 3227
3223 - (void)handleCancelledError:(NSError*)error { 3228 - (void)handleCancelledError:(NSError*)error {
3224 if ([self shouldCancelLoadForCancelledError:error]) { 3229 if ([self shouldCancelLoadForCancelledError:error]) {
3225 [self loadCancelled]; 3230 [self loadCancelled];
3226 [[self sessionController] discardNonCommittedItems]; 3231 [[self sessionController] discardNonCommittedItems];
3227 } 3232 }
3228 } 3233 }
3229 3234
(...skipping 712 matching lines...)
3942 3947
3943 - (void)didShowCreditCardInputOnHTTP { 3948 - (void)didShowCreditCardInputOnHTTP {
3944 DCHECK(!web::IsOriginSecure(self.webState->GetLastCommittedURL())); 3949 DCHECK(!web::IsOriginSecure(self.webState->GetLastCommittedURL()));
3945 web::NavigationItem* item = 3950 web::NavigationItem* item =
3946 _webStateImpl->GetNavigationManager()->GetLastCommittedItem(); 3951 _webStateImpl->GetNavigationManager()->GetLastCommittedItem();
3947 item->GetSSL().content_status |= 3952 item->GetSSL().content_status |=
3948 web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP; 3953 web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP;
3949 _webStateImpl->OnVisibleSecurityStateChange(); 3954 _webStateImpl->OnVisibleSecurityStateChange();
3950 } 3955 }
3951 3956
3952 - (void)handleSSLCertError:(NSError*)error { 3957 - (void)handleSSLCertError:(NSError*)error
3958 forNavigation:(WKNavigation*)navigation {
3953 CHECK(web::IsWKWebViewSSLCertError(error)); 3959 CHECK(web::IsWKWebViewSSLCertError(error));
3954 3960
3955 net::SSLInfo info; 3961 net::SSLInfo info;
3956 web::GetSSLInfoFromWKWebViewSSLCertError(error, &info); 3962 web::GetSSLInfoFromWKWebViewSSLCertError(error, &info);
3957 3963
3958 if (!info.cert) { 3964 if (!info.cert) {
3959 // |info.cert| can be null if certChain in NSError is empty or can not be 3965 // |info.cert| can be null if certChain in NSError is empty or can not be
3960 // parsed, in this case do not ask delegate if error should be allowed, it 3966 // parsed, in this case do not ask delegate if error should be allowed, it
3961 // should not be. 3967 // should not be.
3962 [self handleLoadError:error inMainFrame:YES]; 3968 [self handleLoadError:error inMainFrame:YES forNavigation:navigation];
3963 return; 3969 return;
3964 } 3970 }
3965 3971
3966 // Retrieve verification results from _certVerificationErrors cache to avoid 3972 // Retrieve verification results from _certVerificationErrors cache to avoid
3967 // unnecessary recalculations. Verification results are cached for the leaf 3973 // unnecessary recalculations. Verification results are cached for the leaf
3968 // cert, because the cert chain in |didReceiveAuthenticationChallenge:| is 3974 // cert, because the cert chain in |didReceiveAuthenticationChallenge:| is
3969 // the OS constructed chain, while |chain| is the chain from the server. 3975 // the OS constructed chain, while |chain| is the chain from the server.
3970 NSArray* chain = error.userInfo[web::kNSErrorPeerCertificateChainKey]; 3976 NSArray* chain = error.userInfo[web::kNSErrorPeerCertificateChainKey];
3971 NSURL* requestURL = error.userInfo[web::kNSErrorFailingURLKey]; 3977 NSURL* requestURL = error.userInfo[web::kNSErrorFailingURLKey];
3972 NSString* host = [requestURL host]; 3978 NSString* host = [requestURL host];
(...skipping 179 matching lines...)
4152 } 4158 }
4153 4159
4154 CRWWKScriptMessageRouter* messageRouter = 4160 CRWWKScriptMessageRouter* messageRouter =
4155 [self webViewConfigurationProvider].GetScriptMessageRouter(); 4161 [self webViewConfigurationProvider].GetScriptMessageRouter();
4156 4162
4157 [_POSTRequestLoader loadPOSTRequest:request 4163 [_POSTRequestLoader loadPOSTRequest:request
4158 inWebView:_webView 4164 inWebView:_webView
4159 messageRouter:messageRouter 4165 messageRouter:messageRouter
4160 completionHandler:^(NSError* loadError) { 4166 completionHandler:^(NSError* loadError) {
4161 if (loadError) 4167 if (loadError)
4162 [self handleLoadError:loadError inMainFrame:YES]; 4168 [self handleLoadError:loadError
4169 inMainFrame:YES
4170 forNavigation:nil];
4163 else 4171 else
4164 self.webStateImpl->SetContentsMimeType("text/html"); 4172 self.webStateImpl->SetContentsMimeType("text/html");
4165 }]; 4173 }];
4166 } 4174 }
4167 4175
4168 - (void)loadHTML:(NSString*)HTML forURL:(const GURL&)URL { 4176 - (void)loadHTML:(NSString*)HTML forURL:(const GURL&)URL {
4169 // Remove the transient content view. 4177 // Remove the transient content view.
4170 [self clearTransientContentView]; 4178 [self clearTransientContentView];
4171 4179
4172 _loadPhase = web::LOAD_REQUESTED; 4180 _loadPhase = web::LOAD_REQUESTED;
(...skipping 243 matching lines...)
4416 : WKNavigationResponsePolicyCancel); 4424 : WKNavigationResponsePolicyCancel);
4417 } 4425 }
4418 4426
4419 // TODO(stuartmorgan): Move all the guesswork around these states out of the 4427 // TODO(stuartmorgan): Move all the guesswork around these states out of the
4420 // superclass, and wire these up to the remaining methods. 4428 // superclass, and wire these up to the remaining methods.
4421 - (void)webView:(WKWebView*)webView 4429 - (void)webView:(WKWebView*)webView
4422 didStartProvisionalNavigation:(WKNavigation*)navigation { 4430 didStartProvisionalNavigation:(WKNavigation*)navigation {
4423 [_navigationStates setState:web::WKNavigationState::STARTED 4431 [_navigationStates setState:web::WKNavigationState::STARTED
4424 forNavigation:navigation]; 4432 forNavigation:navigation];
4425 4433
4434 if (navigation &&
4435 ![[_navigationStates lastAddedNavigation] isEqual:navigation]) {
4436 // |navigation| is not the latest navigation and will be cancelled.
4437 // Ignore |navigation| as a new navigation will start soon.
4438 return;
4439 }
4440
4426 GURL webViewURL = net::GURLWithNSURL(webView.URL); 4441 GURL webViewURL = net::GURLWithNSURL(webView.URL);
4427 if (webViewURL.is_empty()) { 4442 if (webViewURL.is_empty()) {
4428 // May happen on iOS9, however in didCommitNavigation: callback the URL 4443 // May happen on iOS9, however in didCommitNavigation: callback the URL
4429 // will be "about:blank". 4444 // will be "about:blank".
4430 webViewURL = GURL(url::kAboutBlankURL); 4445 webViewURL = GURL(url::kAboutBlankURL);
4431 } 4446 }
4432 4447
4433 // Intercept renderer-initiated navigations. If this navigation has not yet 4448 // Intercept renderer-initiated navigations. If this navigation has not yet
4434 // been registered, do so. loadPhase check is necessary because 4449 // been registered, do so. loadPhase check is necessary because
4435 // lastRegisteredRequestURL may be the same as the webViewURL on a new tab 4450 // lastRegisteredRequestURL may be the same as the webViewURL on a new tab
(...skipping 67 matching lines...)
4503 } 4518 }
4504 4519
4505 // Handle load cancellation for directly cancelled navigations without 4520 // Handle load cancellation for directly cancelled navigations without
4506 // handling their potential errors. Otherwise, handle the error. 4521 // handling their potential errors. Otherwise, handle the error.
4507 if ([_pendingNavigationInfo cancelled]) { 4522 if ([_pendingNavigationInfo cancelled]) {
4508 [self loadCancelled]; 4523 [self loadCancelled];
4509 } else { 4524 } else {
4510 error = WKWebViewErrorWithSource(error, PROVISIONAL_LOAD); 4525 error = WKWebViewErrorWithSource(error, PROVISIONAL_LOAD);
4511 4526
4512 if (web::IsWKWebViewSSLCertError(error)) 4527 if (web::IsWKWebViewSSLCertError(error))
4513 [self handleSSLCertError:error]; 4528 [self handleSSLCertError:error forNavigation:navigation];
4514 else 4529 else
4515 [self handleLoadError:error inMainFrame:YES]; 4530 [self handleLoadError:error inMainFrame:YES forNavigation:navigation];
4516 } 4531 }
4517 4532
4518 // This must be reset at the end, since code above may need information about 4533 // This must be reset at the end, since code above may need information about
4519 // the pending load. 4534 // the pending load.
4520 _pendingNavigationInfo.reset(); 4535 _pendingNavigationInfo.reset();
4521 _certVerificationErrors->Clear(); 4536 _certVerificationErrors->Clear();
4522 } 4537 }
4523 4538
4524 - (void)webView:(WKWebView*)webView 4539 - (void)webView:(WKWebView*)webView
4525 didCommitNavigation:(WKNavigation*)navigation { 4540 didCommitNavigation:(WKNavigation*)navigation {
4526 [_navigationStates setState:web::WKNavigationState::COMMITTED 4541 [_navigationStates setState:web::WKNavigationState::COMMITTED
4527 forNavigation:navigation]; 4542 forNavigation:navigation];
4528 4543
4529 DCHECK_EQ(_webView, webView); 4544 DCHECK_EQ(_webView, webView);
4530 _certVerificationErrors->Clear(); 4545 _certVerificationErrors->Clear();
4531 4546
4532 // This is the point where the document's URL has actually changed, and 4547 // This is the point where the document's URL has actually changed, and
4533 // pending navigation information should be applied to state information. 4548 // pending navigation information should be applied to state information.
4534 [self setDocumentURL:net::GURLWithNSURL([_webView URL])]; 4549 [self setDocumentURL:net::GURLWithNSURL([_webView URL])];
4535 4550
4536 if (!_lastRegisteredRequestURL.is_valid() && 4551 if (!_lastRegisteredRequestURL.is_valid() &&
4537 _documentURL != _lastRegisteredRequestURL) { 4552 _documentURL != _lastRegisteredRequestURL) {
4538 // if |_lastRegisteredRequestURL| is an invalid URL, then |_documentURL| 4553 // if |_lastRegisteredRequestURL| is an invalid URL, then |_documentURL|
4539 // will be "about:blank". 4554 // will be "about:blank".
4540 [[self sessionController] updatePendingItem:_documentURL]; 4555 [[self sessionController] updatePendingItem:_documentURL];
4541 } 4556 }
4542 DCHECK(_documentURL == _lastRegisteredRequestURL || 4557
4558 // If |navigation| is nil (which happens for windows open by DOM), then it
4559 // should be the first and the only pending navigaiton.
4560 BOOL isLastNavigation =
4561 !navigation ||
4562 [[_navigationStates lastAddedNavigation] isEqual:navigation];
4563 DCHECK(_documentURL == _lastRegisteredRequestURL || // latest navigation
4564 !isLastNavigation || // previous navigation
4543 (!_lastRegisteredRequestURL.is_valid() && 4565 (!_lastRegisteredRequestURL.is_valid() &&
4544 _documentURL.spec() == url::kAboutBlankURL)); 4566 _documentURL.spec() == url::kAboutBlankURL) /* invalid URL load */);
kkhorimoto 2017/04/18 23:03:15 ditto
Eugene But (OOO till 7-30) 2017/04/19 00:26:46 Done.
4545 4567
4546 self.webStateImpl->UpdateHttpResponseHeaders(_documentURL); 4568 self.webStateImpl->UpdateHttpResponseHeaders(_documentURL);
4547 [self commitPendingNavigationInfo]; 4569 [self commitPendingNavigationInfo];
4548 if ([self currentBackForwardListItemHolder]->navigation_type() == 4570 if ([self currentBackForwardListItemHolder]->navigation_type() ==
4549 WKNavigationTypeBackForward) { 4571 WKNavigationTypeBackForward) {
4550 // A fast back/forward won't call decidePolicyForNavigationResponse, so 4572 // A fast back/forward won't call decidePolicyForNavigationResponse, so
4551 // the MIME type needs to be updated explicitly. 4573 // the MIME type needs to be updated explicitly.
4552 NSString* storedMIMEType = 4574 NSString* storedMIMEType =
4553 [self currentBackForwardListItemHolder]->mime_type(); 4575 [self currentBackForwardListItemHolder]->mime_type();
4554 if (storedMIMEType) { 4576 if (storedMIMEType) {
4555 self.webStateImpl->SetContentsMimeType( 4577 self.webStateImpl->SetContentsMimeType(
4556 base::SysNSStringToUTF8(storedMIMEType)); 4578 base::SysNSStringToUTF8(storedMIMEType));
4557 } 4579 }
4558 } 4580 }
4559 4581
4560 // This point should closely approximate the document object change, so reset 4582 // This point should closely approximate the document object change, so reset
4561 // the list of injected scripts to those that are automatically injected. 4583 // the list of injected scripts to those that are automatically injected.
4562 _injectedScriptManagers.reset([[NSMutableSet alloc] init]); 4584 _injectedScriptManagers.reset([[NSMutableSet alloc] init]);
4563 if ([self contentIsHTML] || self.webState->GetContentsMimeType().empty()) { 4585 if ([self contentIsHTML] || self.webState->GetContentsMimeType().empty()) {
4564 // In unit tests MIME type will be empty, because loadHTML:forURL: does not 4586 // In unit tests MIME type will be empty, because loadHTML:forURL: does not
4565 // notify web view delegate about received response, so web controller does 4587 // notify web view delegate about received response, so web controller does
4566 // not get a chance to properly update MIME type. 4588 // not get a chance to properly update MIME type.
4567 [self injectWindowID]; 4589 [self injectWindowID];
4568 } 4590 }
4569 4591
4570 [self webPageChanged]; 4592 if (isLastNavigation) {
4593 [self webPageChanged];
4594 } else {
4595 // WKWebView has more than one in progress navigaiton, and committed
4596 // navigation was not the latests. It is critical to keep last committed
4597 // URL the same as actual document URL, so try guessing which navigation
4598 // item should be set to current.
4599 // TODO(crbug.com/712269):
4600 for (int i = 0; i < self.navigationManagerImpl->GetItemCount(); i++) {
4601 web::NavigationItem* item = self.navigationManagerImpl->GetItemAtIndex(i);
4602 if (item->GetURL() == _documentURL) {
4603 [self.sessionController goToItemAtIndex:i discardNonCommittedItems:NO];
kkhorimoto 2017/04/18 23:03:15 Could you explain why we aren't discarding the non
Eugene But (OOO till 7-30) 2017/04/19 00:26:46 Done.
4604 }
4605 }
4606 }
4571 self.webStateImpl->OnNavigationCommitted(_documentURL); 4607 self.webStateImpl->OnNavigationCommitted(_documentURL);
4572 4608
4573 [self updateSSLStatusForCurrentNavigationItem]; 4609 [self updateSSLStatusForCurrentNavigationItem];
4574 4610
4575 // Attempt to update the HTML5 history state. 4611 // Attempt to update the HTML5 history state.
4576 [self updateHTML5HistoryState]; 4612 [self updateHTML5HistoryState];
4577 4613
4578 // This is the point where pending entry has been committed, and navigation 4614 // This is the point where pending entry has been committed, and navigation
4579 // item title should be updated. 4615 // item title should be updated.
4580 [self setNavigationItemTitle:[_webView title]]; 4616 [self setNavigationItemTitle:[_webView title]];
(...skipping 11 matching lines...)
4592 didFinishNavigation:(WKNavigation*)navigation { 4628 didFinishNavigation:(WKNavigation*)navigation {
4593 [_navigationStates setState:web::WKNavigationState::FINISHED 4629 [_navigationStates setState:web::WKNavigationState::FINISHED
4594 forNavigation:navigation]; 4630 forNavigation:navigation];
4595 4631
4596 DCHECK(!_isHalted); 4632 DCHECK(!_isHalted);
4597 // Trigger JavaScript driven post-document-load-completion tasks. 4633 // Trigger JavaScript driven post-document-load-completion tasks.
4598 // TODO(crbug.com/546350): Investigate using 4634 // TODO(crbug.com/546350): Investigate using
4599 // WKUserScriptInjectionTimeAtDocumentEnd to inject this material at the 4635 // WKUserScriptInjectionTimeAtDocumentEnd to inject this material at the
4600 // appropriate time rather than invoking here. 4636 // appropriate time rather than invoking here.
4601 web::ExecuteJavaScript(webView, @"__gCrWeb.didFinishNavigation()", nil); 4637 web::ExecuteJavaScript(webView, @"__gCrWeb.didFinishNavigation()", nil);
4602 [self didFinishNavigation]; 4638 [self didFinishNavigation:navigation];
4603 } 4639 }
4604 4640
4605 - (void)webView:(WKWebView*)webView 4641 - (void)webView:(WKWebView*)webView
4606 didFailNavigation:(WKNavigation*)navigation 4642 didFailNavigation:(WKNavigation*)navigation
4607 withError:(NSError*)error { 4643 withError:(NSError*)error {
4608 [_navigationStates setState:web::WKNavigationState::FAILED 4644 [_navigationStates setState:web::WKNavigationState::FAILED
4609 forNavigation:navigation]; 4645 forNavigation:navigation];
4610 4646
4611 [self handleLoadError:WKWebViewErrorWithSource(error, NAVIGATION) 4647 [self handleLoadError:WKWebViewErrorWithSource(error, NAVIGATION)
4612 inMainFrame:YES]; 4648 inMainFrame:YES
4649 forNavigation:navigation];
4613 _certVerificationErrors->Clear(); 4650 _certVerificationErrors->Clear();
4614 } 4651 }
4615 4652
4616 - (void)webView:(WKWebView*)webView 4653 - (void)webView:(WKWebView*)webView
4617 didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge 4654 didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge
4618 completionHandler: 4655 completionHandler:
4619 (void (^)(NSURLSessionAuthChallengeDisposition, 4656 (void (^)(NSURLSessionAuthChallengeDisposition,
4620 NSURLCredential*))completionHandler { 4657 NSURLCredential*))completionHandler {
4621 NSString* authMethod = challenge.protectionSpace.authenticationMethod; 4658 NSString* authMethod = challenge.protectionSpace.authenticationMethod;
4622 if ([authMethod isEqual:NSURLAuthenticationMethodHTTPBasic] || 4659 if ([authMethod isEqual:NSURLAuthenticationMethodHTTPBasic] ||
(...skipping 139 matching lines...)
4762 } else { 4799 } else {
4763 _webStateImpl->OnNavigationCommitted(webViewURL); 4800 _webStateImpl->OnNavigationCommitted(webViewURL);
4764 } 4801 }
4765 } 4802 }
4766 4803
4767 [self updateSSLStatusForCurrentNavigationItem]; 4804 [self updateSSLStatusForCurrentNavigationItem];
4768 4805
4769 // Fast back forward navigation may not call |didFinishNavigation:|, so 4806 // Fast back forward navigation may not call |didFinishNavigation:|, so
4770 // signal did finish navigation explicitly. 4807 // signal did finish navigation explicitly.
4771 if (_lastRegisteredRequestURL == _documentURL) { 4808 if (_lastRegisteredRequestURL == _documentURL) {
4772 [self didFinishNavigation]; 4809 [self didFinishNavigation:nil];
4773 } 4810 }
4774 } 4811 }
4775 4812
4776 - (void)webViewTitleDidChange { 4813 - (void)webViewTitleDidChange {
4777 // WKWebView's title becomes empty when the web process dies; ignore that 4814 // WKWebView's title becomes empty when the web process dies; ignore that
4778 // update. 4815 // update.
4779 if (_webProcessIsDead) { 4816 if (_webProcessIsDead) {
4780 DCHECK_EQ([_webView title].length, 0U); 4817 DCHECK_EQ([_webView title].length, 0U);
4781 return; 4818 return;
4782 } 4819 }
(...skipping 126 matching lines...)
4909 if (![self isLoadRequestPendingForURL:newURL]) 4946 if (![self isLoadRequestPendingForURL:newURL])
4910 [self registerLoadRequest:newURL]; 4947 [self registerLoadRequest:newURL];
4911 } 4948 }
4912 4949
4913 [self setDocumentURL:newURL]; 4950 [self setDocumentURL:newURL];
4914 4951
4915 if (!_changingHistoryState) { 4952 if (!_changingHistoryState) {
4916 [self didStartLoadingURL:_documentURL]; 4953 [self didStartLoadingURL:_documentURL];
4917 _webStateImpl->OnSameDocumentNavigation(newURL); 4954 _webStateImpl->OnSameDocumentNavigation(newURL);
4918 [self updateSSLStatusForCurrentNavigationItem]; 4955 [self updateSSLStatusForCurrentNavigationItem];
4919 [self didFinishNavigation]; 4956 [self didFinishNavigation:nil];
4920 } 4957 }
4921 } 4958 }
4922 4959
4923 - (BOOL)isLoadRequestPendingForURL:(const GURL&)targetURL { 4960 - (BOOL)isLoadRequestPendingForURL:(const GURL&)targetURL {
4924 if (self.loadPhase != web::LOAD_REQUESTED) 4961 if (self.loadPhase != web::LOAD_REQUESTED)
4925 return NO; 4962 return NO;
4926 4963
4927 web::NavigationItem* pendingItem = 4964 web::NavigationItem* pendingItem =
4928 self.webState->GetNavigationManager()->GetPendingItem(); 4965 self.webState->GetNavigationManager()->GetPendingItem();
4929 return pendingItem && pendingItem->GetURL() == targetURL; 4966 return pendingItem && pendingItem->GetURL() == targetURL;
(...skipping 194 matching lines...)
5124 - (void)simulateLoadRequestWithURL:(const GURL&)URL { 5161 - (void)simulateLoadRequestWithURL:(const GURL&)URL {
5125 _lastRegisteredRequestURL = URL; 5162 _lastRegisteredRequestURL = URL;
5126 _loadPhase = web::LOAD_REQUESTED; 5163 _loadPhase = web::LOAD_REQUESTED;
5127 } 5164 }
5128 5165
5129 - (NSString*)referrerFromNavigationAction:(WKNavigationAction*)action { 5166 - (NSString*)referrerFromNavigationAction:(WKNavigationAction*)action {
5130 return [action.request valueForHTTPHeaderField:kReferrerHeaderName]; 5167 return [action.request valueForHTTPHeaderField:kReferrerHeaderName];
5131 } 5168 }
5132 5169
5133 @end 5170 @end
OLDNEW

Powered by Google App Engine