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

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

Issue 2884973005: Look up for pending navigation contexts instead of creating new ones. (Closed)
Patch Set: Rebased Created 3 years, 7 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 | « no previous file | 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 806 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 // Called when WKWebView URL has been changed. 817 // Called when WKWebView URL has been changed.
818 - (void)webViewURLDidChange; 818 - (void)webViewURLDidChange;
819 // Returns YES if a KVO change to |newURL| could be a 'navigation' within the 819 // Returns YES if a KVO change to |newURL| could be a 'navigation' within the
820 // document (hash change, pushState/replaceState, etc.). This should only be 820 // document (hash change, pushState/replaceState, etc.). This should only be
821 // used in the context of a URL KVO callback firing, and only if |isLoading| is 821 // used in the context of a URL KVO callback firing, and only if |isLoading| is
822 // YES for the web view (since if it's not, no guesswork is needed). 822 // YES for the web view (since if it's not, no guesswork is needed).
823 - (BOOL)isKVOChangePotentialSameDocumentNavigationToURL:(const GURL&)newURL; 823 - (BOOL)isKVOChangePotentialSameDocumentNavigationToURL:(const GURL&)newURL;
824 // Called when a non-document-changing URL change occurs. Updates the 824 // Called when a non-document-changing URL change occurs. Updates the
825 // _documentURL, and informs the superclass of the change. 825 // _documentURL, and informs the superclass of the change.
826 - (void)URLDidChangeWithoutDocumentChange:(const GURL&)URL; 826 - (void)URLDidChangeWithoutDocumentChange:(const GURL&)URL;
827 // Returns YES if there is currently a requested but uncommitted load for 827 // Returns context for pending navigation that has |URL|. null if there is no
828 // |targetURL|. 828 // matching pending navigation.
829 - (BOOL)isLoadRequestPendingForURL:(const GURL&)targetURL; 829 - (web::NavigationContextImpl*)contextForPendingNavigationWithURL:
830 (const GURL&)URL;
830 // Loads request for the URL of the current navigation item. Subclasses may 831 // Loads request for the URL of the current navigation item. Subclasses may
831 // choose to build a new NSURLRequest and call |loadRequest| on the underlying 832 // choose to build a new NSURLRequest and call |loadRequest| on the underlying
832 // web view, or use native web view navigation where possible (for example, 833 // web view, or use native web view navigation where possible (for example,
833 // going back and forward through the history stack). 834 // going back and forward through the history stack).
834 - (void)loadRequestForCurrentNavigationItem; 835 - (void)loadRequestForCurrentNavigationItem;
835 // Reports Navigation.IOSWKWebViewSlowFastBackForward UMA. No-op if pending 836 // Reports Navigation.IOSWKWebViewSlowFastBackForward UMA. No-op if pending
836 // navigation is not back forward navigation. 837 // navigation is not back forward navigation.
837 - (void)reportBackForwardNavigationTypeForFastNavigation:(BOOL)isFast; 838 - (void)reportBackForwardNavigationTypeForFastNavigation:(BOOL)isFast;
838 839
839 // Handlers for JavaScript messages. |message| contains a JavaScript command and 840 // Handlers for JavaScript messages. |message| contains a JavaScript command and
(...skipping 3291 matching lines...) Expand 10 before | Expand all | Expand 10 after
4131 4132
4132 // Web View should not be created for App Specific URLs. 4133 // Web View should not be created for App Specific URLs.
4133 if (!web::GetWebClient()->IsAppSpecificURL(URL)) { 4134 if (!web::GetWebClient()->IsAppSpecificURL(URL)) {
4134 [self ensureWebViewCreated]; 4135 [self ensureWebViewCreated];
4135 DCHECK(_webView) << "_webView null while trying to load HTML"; 4136 DCHECK(_webView) << "_webView null while trying to load HTML";
4136 } 4137 }
4137 WKNavigation* navigation = 4138 WKNavigation* navigation =
4138 [_webView loadHTMLString:HTML baseURL:net::NSURLWithGURL(URL)]; 4139 [_webView loadHTMLString:HTML baseURL:net::NSURLWithGURL(URL)];
4139 [_navigationStates setState:web::WKNavigationState::REQUESTED 4140 [_navigationStates setState:web::WKNavigationState::REQUESTED
4140 forNavigation:navigation]; 4141 forNavigation:navigation];
4141 std::unique_ptr<web::NavigationContextImpl> context = 4142 std::unique_ptr<web::NavigationContextImpl> context;
4142 web::NavigationContextImpl::CreateNavigationContext(_webStateImpl, URL); 4143 if (_webStateImpl->HasWebUI()) {
4144 // WebUI uses |loadHTML:forURL:| to feed the content to web view. This
4145 // should not be treated as a navigation, but WKNavigationDelegate callbacks
4146 // still expect a valid context.
4147 context =
4148 web::NavigationContextImpl::CreateNavigationContext(_webStateImpl, URL);
4149 } else {
4150 context = [self
4151 registerLoadRequestForURL:URL
4152 referrer:web::Referrer()
4153 transition:ui::PageTransition::PAGE_TRANSITION_TYPED];
4154 }
4143 [_navigationStates setContext:std::move(context) forNavigation:navigation]; 4155 [_navigationStates setContext:std::move(context) forNavigation:navigation];
4144 } 4156 }
4145 4157
4146 - (void)loadHTML:(NSString*)HTML forAppSpecificURL:(const GURL&)URL { 4158 - (void)loadHTML:(NSString*)HTML forAppSpecificURL:(const GURL&)URL {
4147 CHECK(web::GetWebClient()->IsAppSpecificURL(URL)); 4159 CHECK(web::GetWebClient()->IsAppSpecificURL(URL));
4148 [self loadHTML:HTML forURL:URL]; 4160 [self loadHTML:HTML forURL:URL];
4149 } 4161 }
4150 4162
4151 - (void)loadHTMLForCurrentURL:(NSString*)HTML { 4163 - (void)loadHTMLForCurrentURL:(NSString*)HTML {
4152 [self loadHTML:HTML forURL:self.currentURL]; 4164 [self loadHTML:HTML forURL:self.currentURL];
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
4512 [self setDocumentURL:net::GURLWithNSURL([_webView URL])]; 4524 [self setDocumentURL:net::GURLWithNSURL([_webView URL])];
4513 4525
4514 if (!_lastRegisteredRequestURL.is_valid() && 4526 if (!_lastRegisteredRequestURL.is_valid() &&
4515 _documentURL != _lastRegisteredRequestURL) { 4527 _documentURL != _lastRegisteredRequestURL) {
4516 // if |_lastRegisteredRequestURL| is an invalid URL, then |_documentURL| 4528 // if |_lastRegisteredRequestURL| is an invalid URL, then |_documentURL|
4517 // will be "about:blank". 4529 // will be "about:blank".
4518 [[self sessionController] updatePendingItem:_documentURL]; 4530 [[self sessionController] updatePendingItem:_documentURL];
4519 } 4531 }
4520 4532
4521 // If |navigation| is nil (which happens for windows open by DOM), then it 4533 // If |navigation| is nil (which happens for windows open by DOM), then it
4522 // should be the first and the only pending navigaiton. 4534 // should be the first and the only pending navigation.
4523 BOOL isLastNavigation = 4535 BOOL isLastNavigation =
4524 !navigation || 4536 !navigation ||
4525 [[_navigationStates lastAddedNavigation] isEqual:navigation]; 4537 [[_navigationStates lastAddedNavigation] isEqual:navigation];
4526 DCHECK(_documentURL == _lastRegisteredRequestURL || // latest navigation 4538 DCHECK(_documentURL == _lastRegisteredRequestURL || // latest navigation
4527 !isLastNavigation || // previous navigation 4539 !isLastNavigation || // previous navigation
4528 (!_lastRegisteredRequestURL.is_valid() && // invalid URL load 4540 (!_lastRegisteredRequestURL.is_valid() && // invalid URL load
4529 _documentURL.spec() == url::kAboutBlankURL)); 4541 _documentURL.spec() == url::kAboutBlankURL));
4530 4542
4531 // Update HTTP response headers. 4543 // Update HTTP response headers.
4532 _webStateImpl->UpdateHttpResponseHeaders(_documentURL); 4544 _webStateImpl->UpdateHttpResponseHeaders(_documentURL);
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
4764 // A fast back navigation caused by pushState does not call 4776 // A fast back navigation caused by pushState does not call
4765 // |didCommitNavigation:|, so signal page change explicitly. 4777 // |didCommitNavigation:|, so signal page change explicitly.
4766 // TODO(crbug.com/659816): Because back-forward navigation is disabled for 4778 // TODO(crbug.com/659816): Because back-forward navigation is disabled for
4767 // pages that used push/replace State API, this code will not be executed. 4779 // pages that used push/replace State API, this code will not be executed.
4768 DCHECK_EQ(_documentURL.GetOrigin(), webViewURL.GetOrigin()); 4780 DCHECK_EQ(_documentURL.GetOrigin(), webViewURL.GetOrigin());
4769 BOOL isSameDocumentNavigation = 4781 BOOL isSameDocumentNavigation =
4770 [self isKVOChangePotentialSameDocumentNavigationToURL:webViewURL]; 4782 [self isKVOChangePotentialSameDocumentNavigationToURL:webViewURL];
4771 [self setDocumentURL:webViewURL]; 4783 [self setDocumentURL:webViewURL];
4772 [self webPageChanged]; 4784 [self webPageChanged];
4773 4785
4786 web::NavigationContextImpl* context =
4787 [self contextForPendingNavigationWithURL:webViewURL];
4774 // Same document navigation does not contain response headers. 4788 // Same document navigation does not contain response headers.
4775 // TODO(crbug.com/713836): Instead of creating a new context, find
4776 // existing navigation context stored in |_navigationStates| and use it.
4777 std::unique_ptr<web::NavigationContextImpl> context =
4778 web::NavigationContextImpl::CreateNavigationContext(_webStateImpl,
4779 webViewURL);
4780 net::HttpResponseHeaders* headers = 4789 net::HttpResponseHeaders* headers =
4781 isSameDocumentNavigation ? nullptr 4790 isSameDocumentNavigation ? nullptr
4782 : _webStateImpl->GetHttpResponseHeaders(); 4791 : _webStateImpl->GetHttpResponseHeaders();
4783 context->SetResponseHeaders(headers); 4792 context->SetResponseHeaders(headers);
4784 context->SetIsSameDocument(isSameDocumentNavigation); 4793 context->SetIsSameDocument(isSameDocumentNavigation);
4785 _webStateImpl->OnNavigationFinished(context.get()); 4794 _webStateImpl->OnNavigationFinished(context);
4786 } 4795 }
4787 4796
4788 [self updateSSLStatusForCurrentNavigationItem]; 4797 [self updateSSLStatusForCurrentNavigationItem];
4789 4798
4790 // Fast back forward navigation may not call |didFinishNavigation:|, so 4799 // Fast back forward navigation may not call |didFinishNavigation:|, so
4791 // signal did finish navigation explicitly. 4800 // signal did finish navigation explicitly.
4792 if (_lastRegisteredRequestURL == _documentURL) { 4801 if (_lastRegisteredRequestURL == _documentURL) {
4793 [self didFinishNavigation:nil]; 4802 [self didFinishNavigation:nil];
4794 } 4803 }
4795 } 4804 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
4922 // history changes when a window.history.didPushState or 4931 // history changes when a window.history.didPushState or
4923 // window.history.didReplaceState message is received, which should happen in 4932 // window.history.didReplaceState message is received, which should happen in
4924 // the next runloop. 4933 // the next runloop.
4925 // 4934 //
4926 // Otherwise, simulate the whole delegate flow for a load (since the 4935 // Otherwise, simulate the whole delegate flow for a load (since the
4927 // superclass currently doesn't have a clean separation between URL changes 4936 // superclass currently doesn't have a clean separation between URL changes
4928 // and document changes). Note that the order of these calls is important: 4937 // and document changes). Note that the order of these calls is important:
4929 // registering a load request logically comes before updating the document 4938 // registering a load request logically comes before updating the document
4930 // URL, but also must come first since it uses state that is reset on URL 4939 // URL, but also must come first since it uses state that is reset on URL
4931 // changes. 4940 // changes.
4932 std::unique_ptr<web::NavigationContextImpl> navigationContext; 4941
4942 // |newNavigationContext| only exists if this method has to create a new
4943 // context object.
4944 std::unique_ptr<web::NavigationContextImpl> newNavigationContext;
4933 if (!_changingHistoryState) { 4945 if (!_changingHistoryState) {
4934 if ([self isLoadRequestPendingForURL:newURL]) { 4946 if ([self contextForPendingNavigationWithURL:newURL]) {
4935 // |loadWithParams:| was called with URL that has different fragment 4947 // |loadWithParams:| was called with URL that has different fragment
4936 // comparing to the orevious URL. 4948 // comparing to the previous URL.
kkhorimoto 2017/05/17 23:05:37 Can we restructure this if statement since this co
Eugene But (OOO till 7-30) 2017/05/18 14:47:29 We could but, I wanted to keep a comment to explai
kkhorimoto 2017/05/18 18:32:04 Hmm not a lot of great ways to do it. Maybe we co
Eugene But (OOO till 7-30) 2017/05/18 18:46:22 Thanks! Initially I had raw NavigationContextImpl*
4937 // TODO(crbug.com/713836): Instead of creating a new context, find
4938 // existing navigation context stored in |_navigationStates| and use it.
4939 navigationContext = web::NavigationContextImpl::CreateNavigationContext(
4940 _webStateImpl, newURL);
4941 } else { 4949 } else {
4942 // This could be: 4950 // This could be:
4943 // 1.) Renderer-initiated fragment change 4951 // 1.) Renderer-initiated fragment change
4944 // 2.) Assigning same-origin URL to window.location 4952 // 2.) Assigning same-origin URL to window.location
4945 // 3.) Incorrectly handled window.location.replace (crbug.com/307072) 4953 // 3.) Incorrectly handled window.location.replace (crbug.com/307072)
4946 // 4.) Back-forward same document navigation 4954 // 4.) Back-forward same document navigation
4947 navigationContext = [self registerLoadRequestForURL:newURL]; 4955 newNavigationContext = [self registerLoadRequestForURL:newURL];
4948 4956
4949 // Use the current title for items created by same document navigations. 4957 // Use the current title for items created by same document navigations.
4950 auto* pendingItem = self.navigationManagerImpl->GetPendingItem(); 4958 auto* pendingItem = self.navigationManagerImpl->GetPendingItem();
4951 if (pendingItem) 4959 if (pendingItem)
4952 pendingItem->SetTitle(_webStateImpl->GetTitle()); 4960 pendingItem->SetTitle(_webStateImpl->GetTitle());
4953 } 4961 }
4954 navigationContext->SetIsSameDocument(true);
4955 } 4962 }
4956 4963
4957 [self setDocumentURL:newURL]; 4964 [self setDocumentURL:newURL];
4958 4965
4959 if (!_changingHistoryState) { 4966 if (!_changingHistoryState) {
4960 [self didStartLoadingURL:_documentURL]; 4967 [self didStartLoadingURL:_documentURL];
4961 _webStateImpl->OnNavigationFinished(navigationContext.get()); 4968
4969 // Pass either newly created context (if it exists) or context that already
4970 // existed before.
4971 web::NavigationContextImpl* navigationContext = newNavigationContext.get();
4972 if (!navigationContext)
4973 navigationContext = [self contextForPendingNavigationWithURL:newURL];
4974 navigationContext->SetIsSameDocument(true);
4975 _webStateImpl->OnNavigationFinished(navigationContext);
4976
4962 [self updateSSLStatusForCurrentNavigationItem]; 4977 [self updateSSLStatusForCurrentNavigationItem];
4963 [self didFinishNavigation:nil]; 4978 [self didFinishNavigation:nil];
4964 } 4979 }
4965 } 4980 }
4966 4981
4967 - (BOOL)isLoadRequestPendingForURL:(const GURL&)targetURL { 4982 - (web::NavigationContextImpl*)contextForPendingNavigationWithURL:
4968 if (self.loadPhase != web::LOAD_REQUESTED) 4983 (const GURL&)URL {
4969 return NO; 4984 for (id navigation in [_navigationStates pendingNavigations]) {
4985 if (navigation == [NSNull null]) {
4986 // null is a valid navigation object passed to WKNavigationDelegate
4987 // callbacks and represents window opening action.
4988 navigation = nil;
4989 }
4970 4990
4971 web::NavigationItem* pendingItem = 4991 web::NavigationContextImpl* context =
4972 self.webState->GetNavigationManager()->GetPendingItem(); 4992 [_navigationStates contextForNavigation:navigation];
4973 return pendingItem && pendingItem->GetURL() == targetURL; 4993 if (context->GetUrl() == URL) {
4994 return context;
4995 }
4996 }
4997 return nullptr;
4974 } 4998 }
4975 4999
4976 - (void)loadRequestForCurrentNavigationItem { 5000 - (void)loadRequestForCurrentNavigationItem {
4977 DCHECK(_webView); 5001 DCHECK(_webView);
4978 DCHECK(self.currentNavItem); 5002 DCHECK(self.currentNavItem);
4979 // If a load is kicked off on a WKWebView with a frame whose size is {0, 0} or 5003 // If a load is kicked off on a WKWebView with a frame whose size is {0, 0} or
4980 // that has a negative dimension for a size, rendering issues occur that 5004 // that has a negative dimension for a size, rendering issues occur that
4981 // manifest in erroneous scrolling and tap handling (crbug.com/574996, 5005 // manifest in erroneous scrolling and tap handling (crbug.com/574996,
4982 // crbug.com/577793). 5006 // crbug.com/577793).
4983 DCHECK_GT(CGRectGetWidth([_webView frame]), 0.0); 5007 DCHECK_GT(CGRectGetWidth([_webView frame]), 0.0);
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
5172 - (NSUInteger)observerCount { 5196 - (NSUInteger)observerCount {
5173 DCHECK_EQ(_observerBridges.size(), [_observers count]); 5197 DCHECK_EQ(_observerBridges.size(), [_observers count]);
5174 return [_observers count]; 5198 return [_observers count];
5175 } 5199 }
5176 5200
5177 - (NSString*)referrerFromNavigationAction:(WKNavigationAction*)action { 5201 - (NSString*)referrerFromNavigationAction:(WKNavigationAction*)action {
5178 return [action.request valueForHTTPHeaderField:kReferrerHeaderName]; 5202 return [action.request valueForHTTPHeaderField:kReferrerHeaderName];
5179 } 5203 }
5180 5204
5181 @end 5205 @end
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698