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

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

Issue 2832853002: Handle correctly start and commit of non-latest navigations. (Closed)
Patch Set: Created 3 years, 8 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/navigation/navigation_manager_impl_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 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 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 // Updates the internal state and informs the delegate that any outstanding load 582 // Updates the internal state and informs the delegate that any outstanding load
583 // operations are cancelled. 583 // operations are cancelled.
584 - (void)loadCancelled; 584 - (void)loadCancelled;
585 // If YES, the page should be closed if it successfully redirects to a native 585 // If YES, the page should be closed if it successfully redirects to a native
586 // application, for example if a new tab redirects to the App Store. 586 // application, for example if a new tab redirects to the App Store.
587 - (BOOL)shouldClosePageOnNativeApplicationLoad; 587 - (BOOL)shouldClosePageOnNativeApplicationLoad;
588 // Called following navigation completion to generate final navigation lifecycle 588 // Called following navigation completion to generate final navigation lifecycle
589 // events. Navigation is considered complete when the document has finished 589 // events. Navigation is considered complete when the document has finished
590 // loading, or when other page load mechanics are completed on a 590 // loading, or when other page load mechanics are completed on a
591 // non-document-changing URL change. 591 // non-document-changing URL change.
592 - (void)didFinishNavigation; 592 - (void)didFinishNavigation:(WKNavigation*)navigation;
593 // Update the appropriate parts of the model and broadcast to the embedder. This 593 // Update the appropriate parts of the model and broadcast to the embedder. This
594 // may be called multiple times and thus must be idempotent. 594 // may be called multiple times and thus must be idempotent.
595 - (void)loadCompleteWithSuccess:(BOOL)loadSuccess; 595 - (void)loadCompleteWithSuccess:(BOOL)loadSuccess
596 forNavigation:(WKNavigation*)navigation;
596 // Called after URL is finished loading and _loadPhase is set to PAGE_LOADED. 597 // Called after URL is finished loading and _loadPhase is set to PAGE_LOADED.
597 - (void)didFinishWithURL:(const GURL&)currentURL loadSuccess:(BOOL)loadSuccess; 598 - (void)didFinishWithURL:(const GURL&)currentURL loadSuccess:(BOOL)loadSuccess;
598 // Navigates forwards or backwards by |delta| pages. No-op if delta is out of 599 // Navigates forwards or backwards by |delta| pages. No-op if delta is out of
599 // bounds. Reloads if delta is 0. 600 // bounds. Reloads if delta is 0.
600 // TODO(crbug.com/661316): Move this method to NavigationManager. 601 // TODO(crbug.com/661316): Move this method to NavigationManager.
601 - (void)goDelta:(int)delta; 602 - (void)goDelta:(int)delta;
602 // Informs the native controller if web usage is allowed or not. 603 // Informs the native controller if web usage is allowed or not.
603 - (void)setNativeControllerWebUsageEnabled:(BOOL)webUsageEnabled; 604 - (void)setNativeControllerWebUsageEnabled:(BOOL)webUsageEnabled;
604 // Called when web controller receives a new message from the web page. 605 // Called when web controller receives a new message from the web page.
605 - (void)didReceiveScriptMessage:(WKScriptMessage*)message; 606 - (void)didReceiveScriptMessage:(WKScriptMessage*)message;
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 sourceURL:(const GURL&)sourceURL 723 sourceURL:(const GURL&)sourceURL
723 linkActivatedNavigation:(BOOL)linkActivatedNavigation; 724 linkActivatedNavigation:(BOOL)linkActivatedNavigation;
724 // Returns YES if the navigation action is associated with a main frame request. 725 // Returns YES if the navigation action is associated with a main frame request.
725 - (BOOL)isMainFrameNavigationAction:(WKNavigationAction*)action; 726 - (BOOL)isMainFrameNavigationAction:(WKNavigationAction*)action;
726 // Returns whether external URL navigation action should be opened. 727 // Returns whether external URL navigation action should be opened.
727 - (BOOL)shouldOpenExternalURLForNavigationAction:(WKNavigationAction*)action; 728 - (BOOL)shouldOpenExternalURLForNavigationAction:(WKNavigationAction*)action;
728 // Updates SSL status for the current navigation item based on the information 729 // Updates SSL status for the current navigation item based on the information
729 // provided by web view. 730 // provided by web view.
730 - (void)updateSSLStatusForCurrentNavigationItem; 731 - (void)updateSSLStatusForCurrentNavigationItem;
731 // Called when a load ends in an SSL error and certificate chain. 732 // Called when a load ends in an SSL error and certificate chain.
732 - (void)handleSSLCertError:(NSError*)error; 733 - (void)handleSSLCertError:(NSError*)error forNavigation:navigation;
733 734
734 // Used in webView:didReceiveAuthenticationChallenge:completionHandler: to 735 // Used in webView:didReceiveAuthenticationChallenge:completionHandler: to
735 // reply with NSURLSessionAuthChallengeDisposition and credentials. 736 // reply with NSURLSessionAuthChallengeDisposition and credentials.
736 - (void)processAuthChallenge:(NSURLAuthenticationChallenge*)challenge 737 - (void)processAuthChallenge:(NSURLAuthenticationChallenge*)challenge
737 forCertAcceptPolicy:(web::CertAcceptPolicy)policy 738 forCertAcceptPolicy:(web::CertAcceptPolicy)policy
738 certStatus:(net::CertStatus)certStatus 739 certStatus:(net::CertStatus)certStatus
739 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, 740 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition,
740 NSURLCredential*))completionHandler; 741 NSURLCredential*))completionHandler;
741 // Used in webView:didReceiveAuthenticationChallenge:completionHandler: to reply 742 // Used in webView:didReceiveAuthenticationChallenge:completionHandler: to reply
742 // with NSURLSessionAuthChallengeDisposition and credentials. 743 // with NSURLSessionAuthChallengeDisposition and credentials.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 (base::DictionaryValue*)message 853 (base::DictionaryValue*)message
853 context:(NSDictionary*)context; 854 context:(NSDictionary*)context;
854 855
855 // Returns YES if the given |action| should be allowed to continue. 856 // Returns YES if the given |action| should be allowed to continue.
856 // If this returns NO, the load should be cancelled. 857 // If this returns NO, the load should be cancelled.
857 - (BOOL)shouldAllowLoadWithNavigationAction:(WKNavigationAction*)action; 858 - (BOOL)shouldAllowLoadWithNavigationAction:(WKNavigationAction*)action;
858 // Called when a load ends in an error. 859 // Called when a load ends in an error.
859 // TODO(stuartmorgan): Figure out if there's actually enough shared logic that 860 // TODO(stuartmorgan): Figure out if there's actually enough shared logic that
860 // this makes sense. At the very least remove inMainFrame since that only makes 861 // this makes sense. At the very least remove inMainFrame since that only makes
861 // sense for UIWebView. 862 // sense for UIWebView.
862 - (void)handleLoadError:(NSError*)error inMainFrame:(BOOL)inMainFrame; 863 - (void)handleLoadError:(NSError*)error
864 inMainFrame:(BOOL)inMainFrame
865 forNavigation:(WKNavigation*)navigation;
863 866
864 // Handles cancelled load in WKWebView (error with NSURLErrorCancelled code). 867 // Handles cancelled load in WKWebView (error with NSURLErrorCancelled code).
865 - (void)handleCancelledError:(NSError*)error; 868 - (void)handleCancelledError:(NSError*)error;
866 869
867 // Used to decide whether a load that generates errors with the 870 // Used to decide whether a load that generates errors with the
868 // NSURLErrorCancelled code should be cancelled. 871 // NSURLErrorCancelled code should be cancelled.
869 - (BOOL)shouldCancelLoadForCancelledError:(NSError*)error; 872 - (BOOL)shouldCancelLoadForCancelledError:(NSError*)error;
870 873
871 // Sets up WebUI for URL. 874 // Sets up WebUI for URL.
872 - (void)createWebUIForURL:(const GURL&)URL; 875 - (void)createWebUIForURL:(const GURL&)URL;
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after
2030 web::UserAgentType previousUserAgentType = 2033 web::UserAgentType previousUserAgentType =
2031 previousItem ? previousItem->GetUserAgentType() 2034 previousItem ? previousItem->GetUserAgentType()
2032 : web::UserAgentType::NONE; 2035 : web::UserAgentType::NONE;
2033 [self updateDesktopUserAgentForItem:toItem 2036 [self updateDesktopUserAgentForItem:toItem
2034 previousUserAgentType:previousUserAgentType]; 2037 previousUserAgentType:previousUserAgentType];
2035 2038
2036 BOOL sameDocumentNavigation = 2039 BOOL sameDocumentNavigation =
2037 [sessionController isSameDocumentNavigationBetweenItem:previousItem 2040 [sessionController isSameDocumentNavigationBetweenItem:previousItem
2038 andItem:toItem]; 2041 andItem:toItem];
2039 if (sameDocumentNavigation) { 2042 if (sameDocumentNavigation) {
2040 [sessionController goToItemAtIndex:index]; 2043 [sessionController goToItemAtIndex:index discardNonCommittedItems:YES];
2041 [self updateHTML5HistoryState]; 2044 [self updateHTML5HistoryState];
2042 } else { 2045 } else {
2043 [sessionController discardNonCommittedItems]; 2046 [sessionController discardNonCommittedItems];
2044 [sessionController setPendingItemIndex:index]; 2047 [sessionController setPendingItemIndex:index];
2045 2048
2046 web::NavigationItemImpl* pendingItem = sessionController.pendingItem; 2049 web::NavigationItemImpl* pendingItem = sessionController.pendingItem;
2047 pendingItem->SetTransitionType(ui::PageTransitionFromInt( 2050 pendingItem->SetTransitionType(ui::PageTransitionFromInt(
2048 pendingItem->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK)); 2051 pendingItem->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK));
2049 2052
2050 [self loadCurrentURL]; 2053 [self loadCurrentURL];
2051 } 2054 }
2052 } 2055 }
2053 2056
2054 - (BOOL)isLoaded { 2057 - (BOOL)isLoaded {
2055 return _loadPhase == web::PAGE_LOADED; 2058 return _loadPhase == web::PAGE_LOADED;
2056 } 2059 }
2057 2060
2058 - (void)didFinishNavigation { 2061 - (void)didFinishNavigation:(WKNavigation*)navigation {
2059 // This can be called at multiple times after the document has loaded. Do 2062 // This can be called at multiple times after the document has loaded. Do
2060 // nothing if the document has already loaded. 2063 // nothing if the document has already loaded.
2061 if (_loadPhase == web::PAGE_LOADED) 2064 if (_loadPhase == web::PAGE_LOADED)
2062 return; 2065 return;
2063 [self loadCompleteWithSuccess:YES]; 2066 [self loadCompleteWithSuccess:YES forNavigation:navigation];
2064 } 2067 }
2065 2068
2066 - (void)loadCompleteWithSuccess:(BOOL)loadSuccess { 2069 - (void)loadCompleteWithSuccess:(BOOL)loadSuccess
2070 forNavigation:(WKNavigation*)navigation {
2067 [self removePlaceholderOverlay]; 2071 [self removePlaceholderOverlay];
2068 // The webView may have been torn down (or replaced by a native view). Be 2072 // The webView may have been torn down (or replaced by a native view). Be
2069 // safe and do nothing if that's happened. 2073 // safe and do nothing if that's happened.
2070 if (_loadPhase != web::PAGE_LOADING) 2074 if (_loadPhase != web::PAGE_LOADING)
2071 return; 2075 return;
2072 2076
2073 DCHECK(_webView); 2077 DCHECK(_webView);
2074 2078
2075 const GURL currentURL([self currentURL]); 2079 const GURL currentURL([self currentURL]);
2076 2080
2077 _loadPhase = web::PAGE_LOADED; 2081 _loadPhase = web::PAGE_LOADED;
2078 2082
2079 [self optOutScrollsToTopForSubviews]; 2083 [self optOutScrollsToTopForSubviews];
2080 2084
2081 // Ensure the URL is as expected (and already reported to the delegate). 2085 DCHECK((currentURL == _lastRegisteredRequestURL) || // latest navigation
2082 // If |_lastRegisteredRequestURL| is invalid then |currentURL| will be 2086 // previous navigation
2083 // "about:blank". 2087 ![[_navigationStates lastAddedNavigation] isEqual:navigation] ||
2084 DCHECK((currentURL == _lastRegisteredRequestURL) || 2088 // invalid URL load
2085 (!_lastRegisteredRequestURL.is_valid() && 2089 (!_lastRegisteredRequestURL.is_valid() &&
2086 _documentURL.spec() == url::kAboutBlankURL)) 2090 _documentURL.spec() == url::kAboutBlankURL))
2087 << std::endl 2091 << std::endl
2088 << "currentURL = [" << currentURL << "]" << std::endl 2092 << "currentURL = [" << currentURL << "]" << std::endl
2089 << "_lastRegisteredRequestURL = [" << _lastRegisteredRequestURL << "]"; 2093 << "_lastRegisteredRequestURL = [" << _lastRegisteredRequestURL << "]";
2090 2094
2091 // Perform post-load-finished updates. 2095 // Perform post-load-finished updates.
2092 [self didFinishWithURL:currentURL loadSuccess:loadSuccess]; 2096 [self didFinishWithURL:currentURL loadSuccess:loadSuccess];
2093 2097
2094 // Execute the pending LoadCompleteActions. 2098 // Execute the pending LoadCompleteActions.
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
2784 transition:transition]; 2788 transition:transition];
2785 2789
2786 NSString* replaceWebViewJS = 2790 NSString* replaceWebViewJS =
2787 [self javaScriptToReplaceWebViewURL:pushURL stateObjectJSON:stateObject]; 2791 [self javaScriptToReplaceWebViewURL:pushURL stateObjectJSON:stateObject];
2788 base::WeakNSObject<CRWWebController> weakSelf(self); 2792 base::WeakNSObject<CRWWebController> weakSelf(self);
2789 [self executeJavaScript:replaceWebViewJS completionHandler:^(id, NSError*) { 2793 [self executeJavaScript:replaceWebViewJS completionHandler:^(id, NSError*) {
2790 if (!weakSelf || weakSelf.get()->_isBeingDestroyed) 2794 if (!weakSelf || weakSelf.get()->_isBeingDestroyed)
2791 return; 2795 return;
2792 base::scoped_nsobject<CRWWebController> strongSelf([weakSelf retain]); 2796 base::scoped_nsobject<CRWWebController> strongSelf([weakSelf retain]);
2793 [strongSelf optOutScrollsToTopForSubviews]; 2797 [strongSelf optOutScrollsToTopForSubviews];
2794 [strongSelf didFinishNavigation]; 2798 [strongSelf didFinishNavigation:nil];
2795 }]; 2799 }];
2796 return YES; 2800 return YES;
2797 } 2801 }
2798 2802
2799 - (BOOL)handleWindowHistoryDidReplaceStateMessage: 2803 - (BOOL)handleWindowHistoryDidReplaceStateMessage:
2800 (base::DictionaryValue*)message 2804 (base::DictionaryValue*)message
2801 context:(NSDictionary*)context { 2805 context:(NSDictionary*)context {
2802 DCHECK(_changingHistoryState); 2806 DCHECK(_changingHistoryState);
2803 _changingHistoryState = NO; 2807 _changingHistoryState = NO;
2804 2808
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2839 _URLOnStartLoading = replaceURL; 2843 _URLOnStartLoading = replaceURL;
2840 _lastRegisteredRequestURL = replaceURL; 2844 _lastRegisteredRequestURL = replaceURL;
2841 [self replaceStateWithPageURL:replaceURL stateObject:stateObject]; 2845 [self replaceStateWithPageURL:replaceURL stateObject:stateObject];
2842 NSString* replaceStateJS = [self javaScriptToReplaceWebViewURL:replaceURL 2846 NSString* replaceStateJS = [self javaScriptToReplaceWebViewURL:replaceURL
2843 stateObjectJSON:stateObject]; 2847 stateObjectJSON:stateObject];
2844 base::WeakNSObject<CRWWebController> weakSelf(self); 2848 base::WeakNSObject<CRWWebController> weakSelf(self);
2845 [self executeJavaScript:replaceStateJS completionHandler:^(id, NSError*) { 2849 [self executeJavaScript:replaceStateJS completionHandler:^(id, NSError*) {
2846 if (!weakSelf || weakSelf.get()->_isBeingDestroyed) 2850 if (!weakSelf || weakSelf.get()->_isBeingDestroyed)
2847 return; 2851 return;
2848 base::scoped_nsobject<CRWWebController> strongSelf([weakSelf retain]); 2852 base::scoped_nsobject<CRWWebController> strongSelf([weakSelf retain]);
2849 [strongSelf didFinishNavigation]; 2853 [strongSelf didFinishNavigation:nil];
2850 }]; 2854 }];
2851 return YES; 2855 return YES;
2852 } 2856 }
2853 2857
2854 #pragma mark - 2858 #pragma mark -
2855 2859
2856 - (BOOL)wantsKeyboardShield { 2860 - (BOOL)wantsKeyboardShield {
2857 if ([self.nativeController 2861 if ([self.nativeController
2858 respondsToSelector:@selector(wantsKeyboardShield)]) { 2862 respondsToSelector:@selector(wantsKeyboardShield)]) {
2859 return [self.nativeController wantsKeyboardShield]; 2863 return [self.nativeController wantsKeyboardShield];
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
3074 web::NavigationItemImpl* item = self.currentNavItem; 3078 web::NavigationItemImpl* item = self.currentNavItem;
3075 // TODO(crbug.com/570699): Remove this check once it's no longer possible to 3079 // TODO(crbug.com/570699): Remove this check once it's no longer possible to
3076 // have no current entries. 3080 // have no current entries.
3077 if (item) 3081 if (item)
3078 [self cachePOSTDataForRequest:request inNavigationItem:item]; 3082 [self cachePOSTDataForRequest:request inNavigationItem:item];
3079 } 3083 }
3080 3084
3081 return YES; 3085 return YES;
3082 } 3086 }
3083 3087
3084 - (void)handleLoadError:(NSError*)error inMainFrame:(BOOL)inMainFrame { 3088 - (void)handleLoadError:(NSError*)error
3089 inMainFrame:(BOOL)inMainFrame
3090 forNavigation:(WKNavigation*)navigation {
3085 NSString* MIMEType = [_pendingNavigationInfo MIMEType]; 3091 NSString* MIMEType = [_pendingNavigationInfo MIMEType];
3086 if ([_passKitDownloader isMIMETypePassKitType:MIMEType]) 3092 if ([_passKitDownloader isMIMETypePassKitType:MIMEType])
3087 return; 3093 return;
3088 if ([error code] == NSURLErrorUnsupportedURL) 3094 if ([error code] == NSURLErrorUnsupportedURL)
3089 return; 3095 return;
3090 // In cases where a Plug-in handles the load do not take any further action. 3096 // In cases where a Plug-in handles the load do not take any further action.
3091 if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] && 3097 if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] &&
3092 (error.code == web::kWebKitErrorPlugInLoadFailed || 3098 (error.code == web::kWebKitErrorPlugInLoadFailed ||
3093 error.code == web::kWebKitErrorCannotShowUrl)) 3099 error.code == web::kWebKitErrorCannotShowUrl))
3094 return; 3100 return;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3137 if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] && 3143 if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)] &&
3138 error.code == web::kWebKitErrorFrameLoadInterruptedByPolicyChange) { 3144 error.code == web::kWebKitErrorFrameLoadInterruptedByPolicyChange) {
3139 // See if the delegate wants to handle this case. 3145 // See if the delegate wants to handle this case.
3140 if (errorGURL.is_valid() && 3146 if (errorGURL.is_valid() &&
3141 [_delegate 3147 [_delegate
3142 respondsToSelector:@selector( 3148 respondsToSelector:@selector(
3143 controllerForUnhandledContentAtURL:)]) { 3149 controllerForUnhandledContentAtURL:)]) {
3144 id<CRWNativeContent> controller = 3150 id<CRWNativeContent> controller =
3145 [_delegate controllerForUnhandledContentAtURL:errorGURL]; 3151 [_delegate controllerForUnhandledContentAtURL:errorGURL];
3146 if (controller) { 3152 if (controller) {
3147 [self loadCompleteWithSuccess:NO]; 3153 [self loadCompleteWithSuccess:NO forNavigation:navigation];
3148 [self removeWebViewAllowingCachedReconstruction:NO]; 3154 [self removeWebViewAllowingCachedReconstruction:NO];
3149 [self setNativeController:controller]; 3155 [self setNativeController:controller];
3150 [self loadNativeViewWithSuccess:YES]; 3156 [self loadNativeViewWithSuccess:YES];
3151 return; 3157 return;
3152 } 3158 }
3153 } 3159 }
3154 3160
3155 // Ignore errors that originate from URLs that are opened in external apps. 3161 // Ignore errors that originate from URLs that are opened in external apps.
3156 if ([_openedApplicationURL containsObject:errorURL]) 3162 if ([_openedApplicationURL containsObject:errorURL])
3157 return; 3163 return;
3158 // Certain frame errors don't have URL information for some reason; for 3164 // Certain frame errors don't have URL information for some reason; for
3159 // those cases (so far the only known case is plugin content loaded directly 3165 // those cases (so far the only known case is plugin content loaded directly
3160 // in a frame) just ignore the error. See crbug.com/414295 3166 // in a frame) just ignore the error. See crbug.com/414295
3161 if (!errorURL) { 3167 if (!errorURL) {
3162 DCHECK(!inMainFrame); 3168 DCHECK(!inMainFrame);
3163 return; 3169 return;
3164 } 3170 }
3165 // The wrapper error uses the URL of the error and not the requested URL 3171 // The wrapper error uses the URL of the error and not the requested URL
3166 // (which can be different in case of a redirect) to match desktop Chrome 3172 // (which can be different in case of a redirect) to match desktop Chrome
3167 // behavior. 3173 // behavior.
3168 NSError* wrapperError = [NSError 3174 NSError* wrapperError = [NSError
3169 errorWithDomain:[error domain] 3175 errorWithDomain:[error domain]
3170 code:[error code] 3176 code:[error code]
3171 userInfo:@{ 3177 userInfo:@{
3172 NSURLErrorFailingURLStringErrorKey : [errorURL absoluteString], 3178 NSURLErrorFailingURLStringErrorKey : [errorURL absoluteString],
3173 NSUnderlyingErrorKey : error 3179 NSUnderlyingErrorKey : error
3174 }]; 3180 }];
3175 [self loadCompleteWithSuccess:NO]; 3181 [self loadCompleteWithSuccess:NO forNavigation:navigation];
3176 [self loadErrorInNativeView:wrapperError]; 3182 [self loadErrorInNativeView:wrapperError];
3177 return; 3183 return;
3178 } 3184 }
3179 3185
3180 if ([error code] == NSURLErrorCancelled) { 3186 if ([error code] == NSURLErrorCancelled) {
3181 [self handleCancelledError:error]; 3187 [self handleCancelledError:error];
3182 // NSURLErrorCancelled errors that aren't handled by aborting the load will 3188 // NSURLErrorCancelled errors that aren't handled by aborting the load will
3183 // automatically be retried by the web view, so early return in this case. 3189 // automatically be retried by the web view, so early return in this case.
3184 return; 3190 return;
3185 } 3191 }
3186 3192
3187 [self loadCompleteWithSuccess:NO]; 3193 [self loadCompleteWithSuccess:NO forNavigation:navigation];
3188 [self loadErrorInNativeView:error]; 3194 [self loadErrorInNativeView:error];
3189 } 3195 }
3190 3196
3191 - (void)handleCancelledError:(NSError*)error { 3197 - (void)handleCancelledError:(NSError*)error {
3192 if ([self shouldCancelLoadForCancelledError:error]) { 3198 if ([self shouldCancelLoadForCancelledError:error]) {
3193 [self loadCancelled]; 3199 [self loadCancelled];
3194 [[self sessionController] discardNonCommittedItems]; 3200 [[self sessionController] discardNonCommittedItems];
3195 } 3201 }
3196 } 3202 }
3197 3203
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after
3910 3916
3911 - (void)didShowCreditCardInputOnHTTP { 3917 - (void)didShowCreditCardInputOnHTTP {
3912 DCHECK(!web::IsOriginSecure(self.webState->GetLastCommittedURL())); 3918 DCHECK(!web::IsOriginSecure(self.webState->GetLastCommittedURL()));
3913 web::NavigationItem* item = 3919 web::NavigationItem* item =
3914 _webStateImpl->GetNavigationManager()->GetLastCommittedItem(); 3920 _webStateImpl->GetNavigationManager()->GetLastCommittedItem();
3915 item->GetSSL().content_status |= 3921 item->GetSSL().content_status |=
3916 web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP; 3922 web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP;
3917 _webStateImpl->OnVisibleSecurityStateChange(); 3923 _webStateImpl->OnVisibleSecurityStateChange();
3918 } 3924 }
3919 3925
3920 - (void)handleSSLCertError:(NSError*)error { 3926 - (void)handleSSLCertError:(NSError*)error
3927 forNavigation:(WKNavigation*)navigation {
3921 CHECK(web::IsWKWebViewSSLCertError(error)); 3928 CHECK(web::IsWKWebViewSSLCertError(error));
3922 3929
3923 net::SSLInfo info; 3930 net::SSLInfo info;
3924 web::GetSSLInfoFromWKWebViewSSLCertError(error, &info); 3931 web::GetSSLInfoFromWKWebViewSSLCertError(error, &info);
3925 3932
3926 if (!info.cert) { 3933 if (!info.cert) {
3927 // |info.cert| can be null if certChain in NSError is empty or can not be 3934 // |info.cert| can be null if certChain in NSError is empty or can not be
3928 // parsed, in this case do not ask delegate if error should be allowed, it 3935 // parsed, in this case do not ask delegate if error should be allowed, it
3929 // should not be. 3936 // should not be.
3930 [self handleLoadError:error inMainFrame:YES]; 3937 [self handleLoadError:error inMainFrame:YES forNavigation:navigation];
3931 return; 3938 return;
3932 } 3939 }
3933 3940
3934 // Retrieve verification results from _certVerificationErrors cache to avoid 3941 // Retrieve verification results from _certVerificationErrors cache to avoid
3935 // unnecessary recalculations. Verification results are cached for the leaf 3942 // unnecessary recalculations. Verification results are cached for the leaf
3936 // cert, because the cert chain in |didReceiveAuthenticationChallenge:| is 3943 // cert, because the cert chain in |didReceiveAuthenticationChallenge:| is
3937 // the OS constructed chain, while |chain| is the chain from the server. 3944 // the OS constructed chain, while |chain| is the chain from the server.
3938 NSArray* chain = error.userInfo[web::kNSErrorPeerCertificateChainKey]; 3945 NSArray* chain = error.userInfo[web::kNSErrorPeerCertificateChainKey];
3939 NSURL* requestURL = error.userInfo[web::kNSErrorFailingURLKey]; 3946 NSURL* requestURL = error.userInfo[web::kNSErrorFailingURLKey];
3940 NSString* host = [requestURL host]; 3947 NSString* host = [requestURL host];
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
4120 } 4127 }
4121 4128
4122 CRWWKScriptMessageRouter* messageRouter = 4129 CRWWKScriptMessageRouter* messageRouter =
4123 [self webViewConfigurationProvider].GetScriptMessageRouter(); 4130 [self webViewConfigurationProvider].GetScriptMessageRouter();
4124 4131
4125 [_POSTRequestLoader loadPOSTRequest:request 4132 [_POSTRequestLoader loadPOSTRequest:request
4126 inWebView:_webView 4133 inWebView:_webView
4127 messageRouter:messageRouter 4134 messageRouter:messageRouter
4128 completionHandler:^(NSError* loadError) { 4135 completionHandler:^(NSError* loadError) {
4129 if (loadError) 4136 if (loadError)
4130 [self handleLoadError:loadError inMainFrame:YES]; 4137 [self handleLoadError:loadError
4138 inMainFrame:YES
4139 forNavigation:nil];
4131 else 4140 else
4132 self.webStateImpl->SetContentsMimeType("text/html"); 4141 self.webStateImpl->SetContentsMimeType("text/html");
4133 }]; 4142 }];
4134 } 4143 }
4135 4144
4136 - (void)loadHTML:(NSString*)HTML forURL:(const GURL&)URL { 4145 - (void)loadHTML:(NSString*)HTML forURL:(const GURL&)URL {
4137 // Remove the transient content view. 4146 // Remove the transient content view.
4138 [self clearTransientContentView]; 4147 [self clearTransientContentView];
4139 4148
4140 _loadPhase = web::LOAD_REQUESTED; 4149 _loadPhase = web::LOAD_REQUESTED;
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
4384 : WKNavigationResponsePolicyCancel); 4393 : WKNavigationResponsePolicyCancel);
4385 } 4394 }
4386 4395
4387 // TODO(stuartmorgan): Move all the guesswork around these states out of the 4396 // TODO(stuartmorgan): Move all the guesswork around these states out of the
4388 // superclass, and wire these up to the remaining methods. 4397 // superclass, and wire these up to the remaining methods.
4389 - (void)webView:(WKWebView*)webView 4398 - (void)webView:(WKWebView*)webView
4390 didStartProvisionalNavigation:(WKNavigation*)navigation { 4399 didStartProvisionalNavigation:(WKNavigation*)navigation {
4391 [_navigationStates setState:web::WKNavigationState::STARTED 4400 [_navigationStates setState:web::WKNavigationState::STARTED
4392 forNavigation:navigation]; 4401 forNavigation:navigation];
4393 4402
4403 if (navigation &&
4404 ![[_navigationStates lastAddedNavigation] isEqual:navigation]) {
4405 // |navigation| is not the latest navigation and will be cancelled.
4406 // Ignore |navigation| as a new navigation will start soon.
4407 return;
4408 }
4409
4394 GURL webViewURL = net::GURLWithNSURL(webView.URL); 4410 GURL webViewURL = net::GURLWithNSURL(webView.URL);
4395 if (webViewURL.is_empty()) { 4411 if (webViewURL.is_empty()) {
4396 // May happen on iOS9, however in didCommitNavigation: callback the URL 4412 // May happen on iOS9, however in didCommitNavigation: callback the URL
4397 // will be "about:blank". 4413 // will be "about:blank".
4398 webViewURL = GURL(url::kAboutBlankURL); 4414 webViewURL = GURL(url::kAboutBlankURL);
4399 } 4415 }
4400 4416
4401 // Intercept renderer-initiated navigations. If this navigation has not yet 4417 // Intercept renderer-initiated navigations. If this navigation has not yet
4402 // been registered, do so. loadPhase check is necessary because 4418 // been registered, do so. loadPhase check is necessary because
4403 // lastRegisteredRequestURL may be the same as the webViewURL on a new tab 4419 // lastRegisteredRequestURL may be the same as the webViewURL on a new tab
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
4471 } 4487 }
4472 4488
4473 // Handle load cancellation for directly cancelled navigations without 4489 // Handle load cancellation for directly cancelled navigations without
4474 // handling their potential errors. Otherwise, handle the error. 4490 // handling their potential errors. Otherwise, handle the error.
4475 if ([_pendingNavigationInfo cancelled]) { 4491 if ([_pendingNavigationInfo cancelled]) {
4476 [self loadCancelled]; 4492 [self loadCancelled];
4477 } else { 4493 } else {
4478 error = WKWebViewErrorWithSource(error, PROVISIONAL_LOAD); 4494 error = WKWebViewErrorWithSource(error, PROVISIONAL_LOAD);
4479 4495
4480 if (web::IsWKWebViewSSLCertError(error)) 4496 if (web::IsWKWebViewSSLCertError(error))
4481 [self handleSSLCertError:error]; 4497 [self handleSSLCertError:error forNavigation:navigation];
4482 else 4498 else
4483 [self handleLoadError:error inMainFrame:YES]; 4499 [self handleLoadError:error inMainFrame:YES forNavigation:navigation];
4484 } 4500 }
4485 4501
4486 // This must be reset at the end, since code above may need information about 4502 // This must be reset at the end, since code above may need information about
4487 // the pending load. 4503 // the pending load.
4488 _pendingNavigationInfo.reset(); 4504 _pendingNavigationInfo.reset();
4489 _certVerificationErrors->Clear(); 4505 _certVerificationErrors->Clear();
4490 } 4506 }
4491 4507
4492 - (void)webView:(WKWebView*)webView 4508 - (void)webView:(WKWebView*)webView
4493 didCommitNavigation:(WKNavigation*)navigation { 4509 didCommitNavigation:(WKNavigation*)navigation {
4494 [_navigationStates setState:web::WKNavigationState::COMMITTED 4510 [_navigationStates setState:web::WKNavigationState::COMMITTED
4495 forNavigation:navigation]; 4511 forNavigation:navigation];
4496 4512
4497 DCHECK_EQ(_webView, webView); 4513 DCHECK_EQ(_webView, webView);
4498 _certVerificationErrors->Clear(); 4514 _certVerificationErrors->Clear();
4499 4515
4500 // This is the point where the document's URL has actually changed, and 4516 // This is the point where the document's URL has actually changed, and
4501 // pending navigation information should be applied to state information. 4517 // pending navigation information should be applied to state information.
4502 [self setDocumentURL:net::GURLWithNSURL([_webView URL])]; 4518 [self setDocumentURL:net::GURLWithNSURL([_webView URL])];
4503 4519
4504 if (!_lastRegisteredRequestURL.is_valid() && 4520 if (!_lastRegisteredRequestURL.is_valid() &&
4505 _documentURL != _lastRegisteredRequestURL) { 4521 _documentURL != _lastRegisteredRequestURL) {
4506 // if |_lastRegisteredRequestURL| is an invalid URL, then |_documentURL| 4522 // if |_lastRegisteredRequestURL| is an invalid URL, then |_documentURL|
4507 // will be "about:blank". 4523 // will be "about:blank".
4508 [[self sessionController] updatePendingItem:_documentURL]; 4524 [[self sessionController] updatePendingItem:_documentURL];
4509 } 4525 }
4510 DCHECK(_documentURL == _lastRegisteredRequestURL || 4526
4511 (!_lastRegisteredRequestURL.is_valid() && 4527 // If |navigation| is nil (which happens for windows open by DOM), then it
4528 // should be the first and the only pending navigaiton.
4529 BOOL isLastNavigation =
4530 !navigation ||
4531 [[_navigationStates lastAddedNavigation] isEqual:navigation];
4532 DCHECK(_documentURL == _lastRegisteredRequestURL || // latest navigation
4533 !isLastNavigation || // previous navigation
4534 (!_lastRegisteredRequestURL.is_valid() && // invalid URL load
4512 _documentURL.spec() == url::kAboutBlankURL)); 4535 _documentURL.spec() == url::kAboutBlankURL));
4513 4536
4514 self.webStateImpl->UpdateHttpResponseHeaders(_documentURL); 4537 self.webStateImpl->UpdateHttpResponseHeaders(_documentURL);
4515 [self commitPendingNavigationInfo]; 4538 [self commitPendingNavigationInfo];
4516 if ([self currentBackForwardListItemHolder]->navigation_type() == 4539 if ([self currentBackForwardListItemHolder]->navigation_type() ==
4517 WKNavigationTypeBackForward) { 4540 WKNavigationTypeBackForward) {
4518 // A fast back/forward won't call decidePolicyForNavigationResponse, so 4541 // A fast back/forward won't call decidePolicyForNavigationResponse, so
4519 // the MIME type needs to be updated explicitly. 4542 // the MIME type needs to be updated explicitly.
4520 NSString* storedMIMEType = 4543 NSString* storedMIMEType =
4521 [self currentBackForwardListItemHolder]->mime_type(); 4544 [self currentBackForwardListItemHolder]->mime_type();
4522 if (storedMIMEType) { 4545 if (storedMIMEType) {
4523 self.webStateImpl->SetContentsMimeType( 4546 self.webStateImpl->SetContentsMimeType(
4524 base::SysNSStringToUTF8(storedMIMEType)); 4547 base::SysNSStringToUTF8(storedMIMEType));
4525 } 4548 }
4526 } 4549 }
4527 4550
4528 // This point should closely approximate the document object change, so reset 4551 // This point should closely approximate the document object change, so reset
4529 // the list of injected scripts to those that are automatically injected. 4552 // the list of injected scripts to those that are automatically injected.
4530 _injectedScriptManagers.reset([[NSMutableSet alloc] init]); 4553 _injectedScriptManagers.reset([[NSMutableSet alloc] init]);
4531 if ([self contentIsHTML] || self.webState->GetContentsMimeType().empty()) { 4554 if ([self contentIsHTML] || self.webState->GetContentsMimeType().empty()) {
4532 // In unit tests MIME type will be empty, because loadHTML:forURL: does not 4555 // In unit tests MIME type will be empty, because loadHTML:forURL: does not
4533 // notify web view delegate about received response, so web controller does 4556 // notify web view delegate about received response, so web controller does
4534 // not get a chance to properly update MIME type. 4557 // not get a chance to properly update MIME type.
4535 [self injectWindowID]; 4558 [self injectWindowID];
4536 } 4559 }
4537 4560
4538 [self webPageChanged]; 4561 if (isLastNavigation) {
4562 [self webPageChanged];
4563 } else {
4564 // WKWebView has more than one in progress navigation, and committed
4565 // navigation was not the latest. It is critical to keep last committed
4566 // URL the same as actual document URL, so try guessing which navigation
4567 // item should be set to current.
4568 // TODO(crbug.com/712269):
4569 for (int i = 0; i < self.navigationManagerImpl->GetItemCount(); i++) {
4570 web::NavigationItem* item = self.navigationManagerImpl->GetItemAtIndex(i);
4571 if (item->GetURL() == _documentURL) {
4572 // Do not discard pending entry, because another pending navigation is
4573 // still in progress and will commit or fail soon.
4574 [self.sessionController goToItemAtIndex:i discardNonCommittedItems:NO];
4575 }
4576 }
4577 }
4539 self.webStateImpl->OnNavigationCommitted(_documentURL); 4578 self.webStateImpl->OnNavigationCommitted(_documentURL);
4540 4579
4541 [self updateSSLStatusForCurrentNavigationItem]; 4580 [self updateSSLStatusForCurrentNavigationItem];
4542 4581
4543 // Attempt to update the HTML5 history state. 4582 // Attempt to update the HTML5 history state.
4544 [self updateHTML5HistoryState]; 4583 [self updateHTML5HistoryState];
4545 4584
4546 // This is the point where pending entry has been committed, and navigation 4585 // This is the point where pending entry has been committed, and navigation
4547 // item title should be updated. 4586 // item title should be updated.
4548 [self setNavigationItemTitle:[_webView title]]; 4587 [self setNavigationItemTitle:[_webView title]];
(...skipping 11 matching lines...) Expand all
4560 didFinishNavigation:(WKNavigation*)navigation { 4599 didFinishNavigation:(WKNavigation*)navigation {
4561 [_navigationStates setState:web::WKNavigationState::FINISHED 4600 [_navigationStates setState:web::WKNavigationState::FINISHED
4562 forNavigation:navigation]; 4601 forNavigation:navigation];
4563 4602
4564 DCHECK(!_isHalted); 4603 DCHECK(!_isHalted);
4565 // Trigger JavaScript driven post-document-load-completion tasks. 4604 // Trigger JavaScript driven post-document-load-completion tasks.
4566 // TODO(crbug.com/546350): Investigate using 4605 // TODO(crbug.com/546350): Investigate using
4567 // WKUserScriptInjectionTimeAtDocumentEnd to inject this material at the 4606 // WKUserScriptInjectionTimeAtDocumentEnd to inject this material at the
4568 // appropriate time rather than invoking here. 4607 // appropriate time rather than invoking here.
4569 web::ExecuteJavaScript(webView, @"__gCrWeb.didFinishNavigation()", nil); 4608 web::ExecuteJavaScript(webView, @"__gCrWeb.didFinishNavigation()", nil);
4570 [self didFinishNavigation]; 4609 [self didFinishNavigation:navigation];
4571 } 4610 }
4572 4611
4573 - (void)webView:(WKWebView*)webView 4612 - (void)webView:(WKWebView*)webView
4574 didFailNavigation:(WKNavigation*)navigation 4613 didFailNavigation:(WKNavigation*)navigation
4575 withError:(NSError*)error { 4614 withError:(NSError*)error {
4576 [_navigationStates setState:web::WKNavigationState::FAILED 4615 [_navigationStates setState:web::WKNavigationState::FAILED
4577 forNavigation:navigation]; 4616 forNavigation:navigation];
4578 4617
4579 [self handleLoadError:WKWebViewErrorWithSource(error, NAVIGATION) 4618 [self handleLoadError:WKWebViewErrorWithSource(error, NAVIGATION)
4580 inMainFrame:YES]; 4619 inMainFrame:YES
4620 forNavigation:navigation];
4581 _certVerificationErrors->Clear(); 4621 _certVerificationErrors->Clear();
4582 } 4622 }
4583 4623
4584 - (void)webView:(WKWebView*)webView 4624 - (void)webView:(WKWebView*)webView
4585 didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge 4625 didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge
4586 completionHandler: 4626 completionHandler:
4587 (void (^)(NSURLSessionAuthChallengeDisposition, 4627 (void (^)(NSURLSessionAuthChallengeDisposition,
4588 NSURLCredential*))completionHandler { 4628 NSURLCredential*))completionHandler {
4589 NSString* authMethod = challenge.protectionSpace.authenticationMethod; 4629 NSString* authMethod = challenge.protectionSpace.authenticationMethod;
4590 if ([authMethod isEqual:NSURLAuthenticationMethodHTTPBasic] || 4630 if ([authMethod isEqual:NSURLAuthenticationMethodHTTPBasic] ||
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
4730 } else { 4770 } else {
4731 _webStateImpl->OnNavigationCommitted(webViewURL); 4771 _webStateImpl->OnNavigationCommitted(webViewURL);
4732 } 4772 }
4733 } 4773 }
4734 4774
4735 [self updateSSLStatusForCurrentNavigationItem]; 4775 [self updateSSLStatusForCurrentNavigationItem];
4736 4776
4737 // Fast back forward navigation may not call |didFinishNavigation:|, so 4777 // Fast back forward navigation may not call |didFinishNavigation:|, so
4738 // signal did finish navigation explicitly. 4778 // signal did finish navigation explicitly.
4739 if (_lastRegisteredRequestURL == _documentURL) { 4779 if (_lastRegisteredRequestURL == _documentURL) {
4740 [self didFinishNavigation]; 4780 [self didFinishNavigation:nil];
4741 } 4781 }
4742 } 4782 }
4743 4783
4744 - (void)webViewTitleDidChange { 4784 - (void)webViewTitleDidChange {
4745 // WKWebView's title becomes empty when the web process dies; ignore that 4785 // WKWebView's title becomes empty when the web process dies; ignore that
4746 // update. 4786 // update.
4747 if (_webProcessIsDead) { 4787 if (_webProcessIsDead) {
4748 DCHECK_EQ([_webView title].length, 0U); 4788 DCHECK_EQ([_webView title].length, 0U);
4749 return; 4789 return;
4750 } 4790 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
4877 if (![self isLoadRequestPendingForURL:newURL]) 4917 if (![self isLoadRequestPendingForURL:newURL])
4878 [self registerLoadRequest:newURL]; 4918 [self registerLoadRequest:newURL];
4879 } 4919 }
4880 4920
4881 [self setDocumentURL:newURL]; 4921 [self setDocumentURL:newURL];
4882 4922
4883 if (!_changingHistoryState) { 4923 if (!_changingHistoryState) {
4884 [self didStartLoadingURL:_documentURL]; 4924 [self didStartLoadingURL:_documentURL];
4885 _webStateImpl->OnSameDocumentNavigation(newURL); 4925 _webStateImpl->OnSameDocumentNavigation(newURL);
4886 [self updateSSLStatusForCurrentNavigationItem]; 4926 [self updateSSLStatusForCurrentNavigationItem];
4887 [self didFinishNavigation]; 4927 [self didFinishNavigation:nil];
4888 } 4928 }
4889 } 4929 }
4890 4930
4891 - (BOOL)isLoadRequestPendingForURL:(const GURL&)targetURL { 4931 - (BOOL)isLoadRequestPendingForURL:(const GURL&)targetURL {
4892 if (self.loadPhase != web::LOAD_REQUESTED) 4932 if (self.loadPhase != web::LOAD_REQUESTED)
4893 return NO; 4933 return NO;
4894 4934
4895 web::NavigationItem* pendingItem = 4935 web::NavigationItem* pendingItem =
4896 self.webState->GetNavigationManager()->GetPendingItem(); 4936 self.webState->GetNavigationManager()->GetPendingItem();
4897 return pendingItem && pendingItem->GetURL() == targetURL; 4937 return pendingItem && pendingItem->GetURL() == targetURL;
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
5066 - (void)simulateLoadRequestWithURL:(const GURL&)URL { 5106 - (void)simulateLoadRequestWithURL:(const GURL&)URL {
5067 _lastRegisteredRequestURL = URL; 5107 _lastRegisteredRequestURL = URL;
5068 _loadPhase = web::LOAD_REQUESTED; 5108 _loadPhase = web::LOAD_REQUESTED;
5069 } 5109 }
5070 5110
5071 - (NSString*)referrerFromNavigationAction:(WKNavigationAction*)action { 5111 - (NSString*)referrerFromNavigationAction:(WKNavigationAction*)action {
5072 return [action.request valueForHTTPHeaderField:kReferrerHeaderName]; 5112 return [action.request valueForHTTPHeaderField:kReferrerHeaderName];
5073 } 5113 }
5074 5114
5075 @end 5115 @end
OLDNEW
« no previous file with comments | « ios/web/navigation/navigation_manager_impl_unittest.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698