OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_wk_web_view_web_controller.h" | 5 #import "ios/web/web_state/ui/crw_wk_web_view_web_controller.h" |
6 | 6 |
7 #import <WebKit/WebKit.h> | 7 #import <WebKit/WebKit.h> |
8 | 8 |
9 #include "base/containers/mru_cache.h" | 9 #include "base/containers/mru_cache.h" |
10 #include "base/ios/ios_util.h" | 10 #include "base/ios/ios_util.h" |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 } // namespace | 107 } // namespace |
108 | 108 |
109 @interface CRWWKWebViewWebController ()<WKNavigationDelegate, WKUIDelegate> { | 109 @interface CRWWKWebViewWebController ()<WKNavigationDelegate, WKUIDelegate> { |
110 // The WKWebView managed by this instance. | 110 // The WKWebView managed by this instance. |
111 base::scoped_nsobject<WKWebView> _wkWebView; | 111 base::scoped_nsobject<WKWebView> _wkWebView; |
112 | 112 |
113 // The Watch Dog that detects and reports WKWebView crashes. | 113 // The Watch Dog that detects and reports WKWebView crashes. |
114 base::scoped_nsobject<CRWWKWebViewCrashDetector> _crashDetector; | 114 base::scoped_nsobject<CRWWKWebViewCrashDetector> _crashDetector; |
115 | 115 |
116 // The actual URL of the document object (i.e., the last committed URL). | 116 // The actual URL of the document object (i.e., the last committed URL). |
117 // TODO(stuartmorgan): Remove this in favor of just updating the session | 117 // TODO(crbug.com/549616): Remove this in favor of just updating the |
118 // controller and treating that as authoritative. For now, this allows sharing | 118 // navigation manager and treating that as authoritative. For now, this allows |
119 // the flow that's currently in the superclass. | 119 // sharing the flow that's currently in the superclass. |
120 GURL _documentURL; | 120 GURL _documentURL; |
121 | 121 |
122 // A set of script managers whose scripts have been injected into the current | 122 // A set of script managers whose scripts have been injected into the current |
123 // page. | 123 // page. |
124 // TODO(stuartmorgan): Revisit this approach; it's intended only as a stopgap | 124 // TODO(stuartmorgan): Revisit this approach; it's intended only as a stopgap |
125 // measure to make all the existing script managers work. Longer term, there | 125 // measure to make all the existing script managers work. Longer term, there |
126 // should probably be a couple of points where managers can register to have | 126 // should probably be a couple of points where managers can register to have |
127 // things happen automatically based on page lifecycle, and if they don't want | 127 // things happen automatically based on page lifecycle, and if they don't want |
128 // to use one of those fixed points, they should make their scripts internally | 128 // to use one of those fixed points, they should make their scripts internally |
129 // idempotent. | 129 // idempotent. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 // Cancelled navigations should be simply discarded without handling any | 167 // Cancelled navigations should be simply discarded without handling any |
168 // specific error. | 168 // specific error. |
169 BOOL _pendingNavigationCancelled; | 169 BOOL _pendingNavigationCancelled; |
170 | 170 |
171 // CertVerification errors which happened inside | 171 // CertVerification errors which happened inside |
172 // |webView:didReceiveAuthenticationChallenge:completionHandler:|. | 172 // |webView:didReceiveAuthenticationChallenge:completionHandler:|. |
173 // Key is leaf-cert/host pair. This storage is used to carry calculated | 173 // Key is leaf-cert/host pair. This storage is used to carry calculated |
174 // cert status from |didReceiveAuthenticationChallenge:| to | 174 // cert status from |didReceiveAuthenticationChallenge:| to |
175 // |didFailProvisionalNavigation:| delegate method. | 175 // |didFailProvisionalNavigation:| delegate method. |
176 scoped_ptr<CertVerificationErrorsCacheType> _certVerificationErrors; | 176 scoped_ptr<CertVerificationErrorsCacheType> _certVerificationErrors; |
| 177 |
| 178 // YES if the user has touched the content area since the last URL change. |
| 179 BOOL _touchedSinceLastURLChange; |
177 } | 180 } |
178 | 181 |
179 // Response's MIME type of the last known navigation. | 182 // Response's MIME type of the last known navigation. |
180 @property(nonatomic, copy) NSString* documentMIMEType; | 183 @property(nonatomic, copy) NSString* documentMIMEType; |
181 | 184 |
182 // Dictionary where keys are the names of WKWebView properties and values are | 185 // Dictionary where keys are the names of WKWebView properties and values are |
183 // selector names which should be called when a corresponding property has | 186 // selector names which should be called when a corresponding property has |
184 // changed. e.g. @{ @"URL" : @"webViewURLDidChange" } means that | 187 // changed. e.g. @{ @"URL" : @"webViewURLDidChange" } means that |
185 // -[self webViewURLDidChange] must be called every time when WKWebView.URL is | 188 // -[self webViewURLDidChange] must be called every time when WKWebView.URL is |
186 // changed. | 189 // changed. |
(...skipping 20 matching lines...) Expand all Loading... |
207 | 210 |
208 // Returns a new autoreleased web view created with given configuration. | 211 // Returns a new autoreleased web view created with given configuration. |
209 - (WKWebView*)createWebViewWithConfiguration:(WKWebViewConfiguration*)config; | 212 - (WKWebView*)createWebViewWithConfiguration:(WKWebViewConfiguration*)config; |
210 | 213 |
211 // Sets the value of the webView property, and performs its basic setup. | 214 // Sets the value of the webView property, and performs its basic setup. |
212 - (void)setWebView:(WKWebView*)webView; | 215 - (void)setWebView:(WKWebView*)webView; |
213 | 216 |
214 // Returns whether the given navigation is triggered by a user link click. | 217 // Returns whether the given navigation is triggered by a user link click. |
215 - (BOOL)isLinkNavigation:(WKNavigationType)navigationType; | 218 - (BOOL)isLinkNavigation:(WKNavigationType)navigationType; |
216 | 219 |
| 220 // Sets _documentURL to newURL, and updates any relevant state information. |
| 221 - (void)setDocumentURL:(const GURL&)newURL; |
| 222 |
217 // Sets value of the pendingReferrerString property. | 223 // Sets value of the pendingReferrerString property. |
218 - (void)setPendingReferrerString:(NSString*)referrer; | 224 - (void)setPendingReferrerString:(NSString*)referrer; |
219 | 225 |
220 // Extracts the referrer value from WKNavigationAction and sets it as a pending. | 226 // Extracts the referrer value from WKNavigationAction and sets it as a pending. |
221 // The referrer is known in |decidePolicyForNavigationAction| however it must | 227 // The referrer is known in |decidePolicyForNavigationAction| however it must |
222 // be in a pending state until |didCommitNavigation| where it becames current. | 228 // be in a pending state until |didCommitNavigation| where it becames current. |
223 - (void)updatePendingReferrerFromNavigationAction:(WKNavigationAction*)action; | 229 - (void)updatePendingReferrerFromNavigationAction:(WKNavigationAction*)action; |
224 | 230 |
225 // Replaces the current referrer with the pending one. Referrer becames current | 231 // Replaces the current referrer with the pending one. Referrer becames current |
226 // at |didCommitNavigation| callback. | 232 // at |didCommitNavigation| callback. |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 // TODO(eugenebut): implement dialogs/windows suppression using | 407 // TODO(eugenebut): implement dialogs/windows suppression using |
402 // WKNavigationDelegate methods where possible. | 408 // WKNavigationDelegate methods where possible. |
403 [super setPageDialogOpenPolicy:policy]; | 409 [super setPageDialogOpenPolicy:policy]; |
404 } | 410 } |
405 | 411 |
406 - (void)close { | 412 - (void)close { |
407 [_certVerificationController shutDown]; | 413 [_certVerificationController shutDown]; |
408 [super close]; | 414 [super close]; |
409 } | 415 } |
410 | 416 |
| 417 - (void)touched:(BOOL)touched { |
| 418 [super touched:touched]; |
| 419 if (touched) |
| 420 _touchedSinceLastURLChange = YES; |
| 421 } |
| 422 |
411 #pragma mark - | 423 #pragma mark - |
412 #pragma mark Testing-Only Methods | 424 #pragma mark Testing-Only Methods |
413 | 425 |
414 - (void)injectWebViewContentView:(CRWWebViewContentView*)webViewContentView { | 426 - (void)injectWebViewContentView:(CRWWebViewContentView*)webViewContentView { |
415 [super injectWebViewContentView:webViewContentView]; | 427 [super injectWebViewContentView:webViewContentView]; |
416 [self setWebView:static_cast<WKWebView*>(webViewContentView.webView)]; | 428 [self setWebView:static_cast<WKWebView*>(webViewContentView.webView)]; |
417 } | 429 } |
418 | 430 |
419 #pragma mark - Protected property implementations | 431 #pragma mark - Protected property implementations |
420 | 432 |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 name:kScriptImmediateName | 758 name:kScriptImmediateName |
747 webView:webView]; | 759 webView:webView]; |
748 } | 760 } |
749 [_wkWebView setNavigationDelegate:self]; | 761 [_wkWebView setNavigationDelegate:self]; |
750 [_wkWebView setUIDelegate:self]; | 762 [_wkWebView setUIDelegate:self]; |
751 for (NSString* keyPath in self.wkWebViewObservers) { | 763 for (NSString* keyPath in self.wkWebViewObservers) { |
752 [_wkWebView addObserver:self forKeyPath:keyPath options:0 context:nullptr]; | 764 [_wkWebView addObserver:self forKeyPath:keyPath options:0 context:nullptr]; |
753 } | 765 } |
754 _injectedScriptManagers.reset([[NSMutableSet alloc] init]); | 766 _injectedScriptManagers.reset([[NSMutableSet alloc] init]); |
755 _crashDetector.reset([self newCrashDetectorWithWebView:_wkWebView]); | 767 _crashDetector.reset([self newCrashDetectorWithWebView:_wkWebView]); |
756 _documentURL = [self defaultURL]; | 768 [self setDocumentURL:[self defaultURL]]; |
757 } | 769 } |
758 | 770 |
759 - (BOOL)isLinkNavigation:(WKNavigationType)navigationType { | 771 - (BOOL)isLinkNavigation:(WKNavigationType)navigationType { |
760 switch (navigationType) { | 772 switch (navigationType) { |
761 case WKNavigationTypeLinkActivated: | 773 case WKNavigationTypeLinkActivated: |
762 return YES; | 774 return YES; |
763 case WKNavigationTypeOther: | 775 case WKNavigationTypeOther: |
764 return [self userClickedRecently]; | 776 return [self userClickedRecently]; |
765 default: | 777 default: |
766 return NO; | 778 return NO; |
767 } | 779 } |
768 } | 780 } |
769 | 781 |
| 782 - (void)setDocumentURL:(const GURL&)newURL { |
| 783 if (newURL != _documentURL) { |
| 784 _documentURL = newURL; |
| 785 _touchedSinceLastURLChange = NO; |
| 786 } |
| 787 } |
| 788 |
770 - (void)setPendingReferrerString:(NSString*)referrer { | 789 - (void)setPendingReferrerString:(NSString*)referrer { |
771 _pendingReferrerString.reset([referrer copy]); | 790 _pendingReferrerString.reset([referrer copy]); |
772 } | 791 } |
773 | 792 |
774 - (void)updatePendingReferrerFromNavigationAction:(WKNavigationAction*)action { | 793 - (void)updatePendingReferrerFromNavigationAction:(WKNavigationAction*)action { |
775 if (action.targetFrame.mainFrame) | 794 if (action.targetFrame.mainFrame) |
776 [self setPendingReferrerString:GetRefererFromNavigationAction(action)]; | 795 [self setPendingReferrerString:GetRefererFromNavigationAction(action)]; |
777 } | 796 } |
778 | 797 |
779 - (void)commitPendingReferrerString { | 798 - (void)commitPendingReferrerString { |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1127 base::SysNSStringToUTF8(challenge.protectionSpace.host); | 1146 base::SysNSStringToUTF8(challenge.protectionSpace.host); |
1128 _certVerificationErrors->Put( | 1147 _certVerificationErrors->Put( |
1129 web::CertHostPair(leafCert, host), | 1148 web::CertHostPair(leafCert, host), |
1130 CertVerificationError(is_recoverable, certStatus)); | 1149 CertVerificationError(is_recoverable, certStatus)); |
1131 } | 1150 } |
1132 } | 1151 } |
1133 completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); | 1152 completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); |
1134 } | 1153 } |
1135 | 1154 |
1136 - (void)registerLoadRequest:(const GURL&)url { | 1155 - (void)registerLoadRequest:(const GURL&)url { |
1137 // If load request is registered via WKWebViewWebController, assume transition | 1156 // Get the navigation type from the last main frame load request, and try to |
1138 // is link or client redirect as other transitions will already be registered | 1157 // map that to a PageTransition. |
1139 // by web controller or delegates. | 1158 WKNavigationType navigationType = _pendingNavigationTypeForMainFrame |
1140 // TODO(stuartmorgan): Remove guesswork and replace with information from | 1159 ? *_pendingNavigationTypeForMainFrame |
1141 // decidePolicyForNavigationAction:. | 1160 : WKNavigationTypeOther; |
1142 ui::PageTransition transition = self.userInteractionRegistered | 1161 ui::PageTransition transition = ui::PAGE_TRANSITION_CLIENT_REDIRECT; |
1143 ? ui::PAGE_TRANSITION_LINK | 1162 switch (navigationType) { |
1144 : ui::PAGE_TRANSITION_CLIENT_REDIRECT; | 1163 case WKNavigationTypeLinkActivated: |
| 1164 transition = ui::PAGE_TRANSITION_LINK; |
| 1165 break; |
| 1166 case WKNavigationTypeFormSubmitted: |
| 1167 case WKNavigationTypeFormResubmitted: |
| 1168 transition = ui::PAGE_TRANSITION_FORM_SUBMIT; |
| 1169 break; |
| 1170 case WKNavigationTypeBackForward: |
| 1171 transition = ui::PAGE_TRANSITION_FORWARD_BACK; |
| 1172 break; |
| 1173 case WKNavigationTypeReload: |
| 1174 transition = ui::PAGE_TRANSITION_RELOAD; |
| 1175 break; |
| 1176 case WKNavigationTypeOther: |
| 1177 // The "Other" type covers a variety of very different cases, which may |
| 1178 // or may not be the result of user actions. For now, guess based on |
| 1179 // whether there's been a touch since the last URL change. |
| 1180 // TODO(crbug.com/549301): See if this heuristic can be improved. |
| 1181 transition = _touchedSinceLastURLChange |
| 1182 ? ui::PAGE_TRANSITION_LINK |
| 1183 : ui::PAGE_TRANSITION_CLIENT_REDIRECT; |
| 1184 break; |
| 1185 } |
1145 // The referrer is not known yet, and will be updated later. | 1186 // The referrer is not known yet, and will be updated later. |
1146 const web::Referrer emptyReferrer; | 1187 const web::Referrer emptyReferrer; |
1147 [self registerLoadRequest:url referrer:emptyReferrer transition:transition]; | 1188 [self registerLoadRequest:url referrer:emptyReferrer transition:transition]; |
1148 } | 1189 } |
1149 | 1190 |
1150 - (void)URLDidChangeWithoutDocumentChange:(const GURL&)newURL { | 1191 - (void)URLDidChangeWithoutDocumentChange:(const GURL&)newURL { |
1151 DCHECK(newURL == net::GURLWithNSURL([_wkWebView URL])); | 1192 DCHECK(newURL == net::GURLWithNSURL([_wkWebView URL])); |
1152 DCHECK_EQ(_documentURL.host(), newURL.host()); | 1193 DCHECK_EQ(_documentURL.host(), newURL.host()); |
1153 _documentURL = newURL; | 1194 [self setDocumentURL:newURL]; |
1154 // If called during window.history.pushState or window.history.replaceState | 1195 // If called during window.history.pushState or window.history.replaceState |
1155 // JavaScript evaluation, only update the document URL. This callback does not | 1196 // JavaScript evaluation, only update the document URL. This callback does not |
1156 // have any information about the state object and cannot create (or edit) the | 1197 // have any information about the state object and cannot create (or edit) the |
1157 // navigation entry for this page change. Web controller will sync with | 1198 // navigation entry for this page change. Web controller will sync with |
1158 // history changes when a window.history.didPushState or | 1199 // history changes when a window.history.didPushState or |
1159 // window.history.didReplaceState message is received, which should happen in | 1200 // window.history.didReplaceState message is received, which should happen in |
1160 // the next runloop. | 1201 // the next runloop. |
1161 if (!_changingHistoryState) { | 1202 if (!_changingHistoryState) { |
1162 [self registerLoadRequest:_documentURL]; | 1203 [self registerLoadRequest:_documentURL]; |
1163 [self didStartLoadingURL:_documentURL updateHistory:YES]; | 1204 [self didStartLoadingURL:_documentURL updateHistory:YES]; |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 _certVerificationErrors->Clear(); | 1595 _certVerificationErrors->Clear(); |
1555 // This point should closely approximate the document object change, so reset | 1596 // This point should closely approximate the document object change, so reset |
1556 // the list of injected scripts to those that are automatically injected. | 1597 // the list of injected scripts to those that are automatically injected. |
1557 _injectedScriptManagers.reset([[NSMutableSet alloc] init]); | 1598 _injectedScriptManagers.reset([[NSMutableSet alloc] init]); |
1558 [self injectWindowID]; | 1599 [self injectWindowID]; |
1559 | 1600 |
1560 // The page has changed; commit the pending referrer. | 1601 // The page has changed; commit the pending referrer. |
1561 [self commitPendingReferrerString]; | 1602 [self commitPendingReferrerString]; |
1562 | 1603 |
1563 // This is the point where the document's URL has actually changed. | 1604 // This is the point where the document's URL has actually changed. |
1564 _documentURL = net::GURLWithNSURL([_wkWebView URL]); | 1605 [self setDocumentURL:net::GURLWithNSURL([_wkWebView URL])]; |
1565 DCHECK(_documentURL == self.lastRegisteredRequestURL); | 1606 DCHECK(_documentURL == self.lastRegisteredRequestURL); |
1566 [self webPageChanged]; | 1607 [self webPageChanged]; |
1567 | 1608 |
1568 [self updateCurrentBackForwardListItemHolder]; | 1609 [self updateCurrentBackForwardListItemHolder]; |
1569 | 1610 |
1570 #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) | 1611 #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) |
1571 [self updateSSLStatusForCurrentNavigationItem]; | 1612 [self updateSSLStatusForCurrentNavigationItem]; |
1572 #endif | 1613 #endif |
1573 | 1614 |
1574 // Report cases where SSL cert is missing for a secure connection. | 1615 // Report cases where SSL cert is missing for a secure connection. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1719 placeholderText:defaultText | 1760 placeholderText:defaultText |
1720 requestURL: | 1761 requestURL: |
1721 net::GURLWithNSURL(frame.request.URL) | 1762 net::GURLWithNSURL(frame.request.URL) |
1722 completionHandler:completionHandler]; | 1763 completionHandler:completionHandler]; |
1723 } else if (completionHandler) { | 1764 } else if (completionHandler) { |
1724 completionHandler(nil); | 1765 completionHandler(nil); |
1725 } | 1766 } |
1726 } | 1767 } |
1727 | 1768 |
1728 @end | 1769 @end |
OLD | NEW |