| 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 |