| OLD | NEW |
| 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 <objc/runtime.h> | 7 #import <objc/runtime.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <cmath> | 10 #include <cmath> |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 // Each observer in |_observers| is associated with a | 262 // Each observer in |_observers| is associated with a |
| 263 // WebControllerObserverBridge in order to listen from WebState callbacks. | 263 // WebControllerObserverBridge in order to listen from WebState callbacks. |
| 264 // TODO(droger): Remove |_observerBridges| when all CRWWebControllerObservers | 264 // TODO(droger): Remove |_observerBridges| when all CRWWebControllerObservers |
| 265 // are converted to WebStateObservers. | 265 // are converted to WebStateObservers. |
| 266 ScopedVector<web::WebControllerObserverBridge> _observerBridges; | 266 ScopedVector<web::WebControllerObserverBridge> _observerBridges; |
| 267 // |windowId| that is saved when a page changes. Used to detect refreshes. | 267 // |windowId| that is saved when a page changes. Used to detect refreshes. |
| 268 base::scoped_nsobject<NSString> _lastSeenWindowID; | 268 base::scoped_nsobject<NSString> _lastSeenWindowID; |
| 269 // YES if a user interaction has been registered at any time once the page has | 269 // YES if a user interaction has been registered at any time once the page has |
| 270 // loaded. | 270 // loaded. |
| 271 BOOL _userInteractionRegistered; | 271 BOOL _userInteractionRegistered; |
| 272 // YES if the user has interacted with the content area since the last URL |
| 273 // change. |
| 274 BOOL _interactionRegisteredSinceLastURLChange; |
| 275 // The actual URL of the document object (i.e., the last committed URL). |
| 276 // TODO(crbug.com/549616): Remove this in favor of just updating the |
| 277 // navigation manager and treating that as authoritative. |
| 278 GURL _documentURL; |
| 272 // Last URL change reported to webWill/DidStartLoadingURL. Used to detect page | 279 // Last URL change reported to webWill/DidStartLoadingURL. Used to detect page |
| 273 // location changes (client redirects) in practice. | 280 // location changes (client redirects) in practice. |
| 274 GURL _lastRegisteredRequestURL; | 281 GURL _lastRegisteredRequestURL; |
| 275 // Last URL change reported to webDidStartLoadingURL. Used to detect page | 282 // Last URL change reported to webDidStartLoadingURL. Used to detect page |
| 276 // location changes in practice. | 283 // location changes in practice. |
| 277 GURL _URLOnStartLoading; | 284 GURL _URLOnStartLoading; |
| 278 // Page loading phase. | 285 // Page loading phase. |
| 279 web::LoadPhase _loadPhase; | 286 web::LoadPhase _loadPhase; |
| 280 // The web::PageDisplayState recorded when the page starts loading. | 287 // The web::PageDisplayState recorded when the page starts loading. |
| 281 web::PageDisplayState _displayStateOnStartLoading; | 288 web::PageDisplayState _displayStateOnStartLoading; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 // Returns a new autoreleased web view created with given configuration. | 467 // Returns a new autoreleased web view created with given configuration. |
| 461 - (WKWebView*)createWebViewWithConfiguration:(WKWebViewConfiguration*)config; | 468 - (WKWebView*)createWebViewWithConfiguration:(WKWebViewConfiguration*)config; |
| 462 // Sets the value of the webView property, and performs its basic setup. | 469 // Sets the value of the webView property, and performs its basic setup. |
| 463 - (void)setWebView:(WKWebView*)webView; | 470 - (void)setWebView:(WKWebView*)webView; |
| 464 // Destroys the web view by setting webView property to nil. | 471 // Destroys the web view by setting webView property to nil. |
| 465 - (void)resetWebView; | 472 - (void)resetWebView; |
| 466 // Returns the WKWebViewConfigurationProvider associated with the web | 473 // Returns the WKWebViewConfigurationProvider associated with the web |
| 467 // controller's BrowserState. | 474 // controller's BrowserState. |
| 468 - (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider; | 475 - (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider; |
| 469 | 476 |
| 477 // Returns the current URL of the web view, and sets |trustLevel| accordingly |
| 478 // based on the confidence in the verification. |
| 479 - (GURL)webURLWithTrustLevel:(web::URLVerificationTrustLevel*)trustLevel; |
| 470 // Returns |YES| if |url| should be loaded in a native view. | 480 // Returns |YES| if |url| should be loaded in a native view. |
| 471 - (BOOL)shouldLoadURLInNativeView:(const GURL&)url; | 481 - (BOOL)shouldLoadURLInNativeView:(const GURL&)url; |
| 472 // Loads the HTML into the page at the given URL. | 482 // Loads the HTML into the page at the given URL. |
| 473 - (void)loadHTML:(NSString*)html forURL:(const GURL&)url; | 483 - (void)loadHTML:(NSString*)html forURL:(const GURL&)url; |
| 474 // Loads the current nativeController in a native view. If a web view is | 484 // Loads the current nativeController in a native view. If a web view is |
| 475 // present, removes it and swaps in the native view in its place. | 485 // present, removes it and swaps in the native view in its place. |
| 476 - (void)loadNativeViewWithSuccess:(BOOL)loadSuccess; | 486 - (void)loadNativeViewWithSuccess:(BOOL)loadSuccess; |
| 477 // YES if the navigation to |url| should be treated as a reload. | 487 // YES if the navigation to |url| should be treated as a reload. |
| 478 - (BOOL)shouldReload:(const GURL&)destinationURL | 488 - (BOOL)shouldReload:(const GURL&)destinationURL |
| 479 transition:(ui::PageTransition)transition; | 489 transition:(ui::PageTransition)transition; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 // stack. A state object is a serialized generic JavaScript object that contains | 580 // stack. A state object is a serialized generic JavaScript object that contains |
| 571 // details of the UI's state for a given CRWSessionEntry/URL. | 581 // details of the UI's state for a given CRWSessionEntry/URL. |
| 572 // TODO(stuartmorgan): Move the pushState/replaceState logic into | 582 // TODO(stuartmorgan): Move the pushState/replaceState logic into |
| 573 // NavigationManager. | 583 // NavigationManager. |
| 574 - (void)pushStateWithPageURL:(const GURL&)pageURL | 584 - (void)pushStateWithPageURL:(const GURL&)pageURL |
| 575 stateObject:(NSString*)stateObject | 585 stateObject:(NSString*)stateObject |
| 576 transition:(ui::PageTransition)transition; | 586 transition:(ui::PageTransition)transition; |
| 577 // Assigns the given URL and state object to the current CRWSessionEntry. | 587 // Assigns the given URL and state object to the current CRWSessionEntry. |
| 578 - (void)replaceStateWithPageURL:(const GURL&)pageUrl | 588 - (void)replaceStateWithPageURL:(const GURL&)pageUrl |
| 579 stateObject:(NSString*)stateObject; | 589 stateObject:(NSString*)stateObject; |
| 590 // Sets _documentURL to newURL, and updates any relevant state information. |
| 591 - (void)setDocumentURL:(const GURL&)newURL; |
| 580 // Returns YES if the current navigation item corresponds to a web page | 592 // Returns YES if the current navigation item corresponds to a web page |
| 581 // loaded by a POST request. | 593 // loaded by a POST request. |
| 582 - (BOOL)isCurrentNavigationItemPOST; | 594 - (BOOL)isCurrentNavigationItemPOST; |
| 583 // Returns whether the given navigation is triggered by a user link click. | 595 // Returns whether the given navigation is triggered by a user link click. |
| 584 - (BOOL)isLinkNavigation:(WKNavigationType)navigationType; | 596 - (BOOL)isLinkNavigation:(WKNavigationType)navigationType; |
| 585 | 597 |
| 586 // Finds all the scrollviews in the view hierarchy and makes sure they do not | 598 // Finds all the scrollviews in the view hierarchy and makes sure they do not |
| 587 // interfere with scroll to top when tapping the statusbar. | 599 // interfere with scroll to top when tapping the statusbar. |
| 588 - (void)optOutScrollsToTopForSubviews; | 600 - (void)optOutScrollsToTopForSubviews; |
| 589 // Tears down the old native controller, and then replaces it with the new one. | 601 // Tears down the old native controller, and then replaces it with the new one. |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 self.userInteractionRegistered = NO; | 1370 self.userInteractionRegistered = NO; |
| 1359 } | 1371 } |
| 1360 | 1372 |
| 1361 - (void)replaceStateWithPageURL:(const GURL&)pageUrl | 1373 - (void)replaceStateWithPageURL:(const GURL&)pageUrl |
| 1362 stateObject:(NSString*)stateObject { | 1374 stateObject:(NSString*)stateObject { |
| 1363 [[self sessionController] updateCurrentEntryWithURL:pageUrl | 1375 [[self sessionController] updateCurrentEntryWithURL:pageUrl |
| 1364 stateObject:stateObject]; | 1376 stateObject:stateObject]; |
| 1365 [self didUpdateHistoryStateWithPageURL:pageUrl]; | 1377 [self didUpdateHistoryStateWithPageURL:pageUrl]; |
| 1366 } | 1378 } |
| 1367 | 1379 |
| 1380 - (void)setDocumentURL:(const GURL&)newURL { |
| 1381 if (newURL != _documentURL) { |
| 1382 _documentURL = newURL; |
| 1383 _interactionRegisteredSinceLastURLChange = NO; |
| 1384 } |
| 1385 } |
| 1386 |
| 1368 - (BOOL)isCurrentNavigationItemPOST { | 1387 - (BOOL)isCurrentNavigationItemPOST { |
| 1369 // |_pendingNavigationInfo| will be nil if the decidePolicy* delegate methods | 1388 // |_pendingNavigationInfo| will be nil if the decidePolicy* delegate methods |
| 1370 // were not called. | 1389 // were not called. |
| 1371 WKNavigationType type = | 1390 WKNavigationType type = |
| 1372 _pendingNavigationInfo | 1391 _pendingNavigationInfo |
| 1373 ? [_pendingNavigationInfo navigationType] | 1392 ? [_pendingNavigationInfo navigationType] |
| 1374 : [self currentBackForwardListItemHolder]->navigation_type(); | 1393 : [self currentBackForwardListItemHolder]->navigation_type(); |
| 1375 return type == WKNavigationTypeFormSubmitted || | 1394 return type == WKNavigationTypeFormSubmitted || |
| 1376 type == WKNavigationTypeFormResubmitted; | 1395 type == WKNavigationTypeFormResubmitted; |
| 1377 } | 1396 } |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1565 transition = ui::PAGE_TRANSITION_FORWARD_BACK; | 1584 transition = ui::PAGE_TRANSITION_FORWARD_BACK; |
| 1566 break; | 1585 break; |
| 1567 case WKNavigationTypeReload: | 1586 case WKNavigationTypeReload: |
| 1568 transition = ui::PAGE_TRANSITION_RELOAD; | 1587 transition = ui::PAGE_TRANSITION_RELOAD; |
| 1569 break; | 1588 break; |
| 1570 case WKNavigationTypeOther: | 1589 case WKNavigationTypeOther: |
| 1571 // The "Other" type covers a variety of very different cases, which may | 1590 // The "Other" type covers a variety of very different cases, which may |
| 1572 // or may not be the result of user actions. For now, guess based on | 1591 // or may not be the result of user actions. For now, guess based on |
| 1573 // whether there's been an interaction since the last URL change. | 1592 // whether there's been an interaction since the last URL change. |
| 1574 // TODO(crbug.com/549301): See if this heuristic can be improved. | 1593 // TODO(crbug.com/549301): See if this heuristic can be improved. |
| 1575 transition = self.interactionRegisteredSinceLastURLChange | 1594 transition = _interactionRegisteredSinceLastURLChange |
| 1576 ? ui::PAGE_TRANSITION_LINK | 1595 ? ui::PAGE_TRANSITION_LINK |
| 1577 : ui::PAGE_TRANSITION_CLIENT_REDIRECT; | 1596 : ui::PAGE_TRANSITION_CLIENT_REDIRECT; |
| 1578 break; | 1597 break; |
| 1579 } | 1598 } |
| 1580 // The referrer is not known yet, and will be updated later. | 1599 // The referrer is not known yet, and will be updated later. |
| 1581 const web::Referrer emptyReferrer; | 1600 const web::Referrer emptyReferrer; |
| 1582 [self registerLoadRequest:URL referrer:emptyReferrer transition:transition]; | 1601 [self registerLoadRequest:URL referrer:emptyReferrer transition:transition]; |
| 1583 } | 1602 } |
| 1584 | 1603 |
| 1585 - (void)registerLoadRequest:(const GURL&)requestURL | 1604 - (void)registerLoadRequest:(const GURL&)requestURL |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1940 [self loadCurrentURLInNativeView]; | 1959 [self loadCurrentURLInNativeView]; |
| 1941 } else { | 1960 } else { |
| 1942 [self loadCurrentURLInWebView]; | 1961 [self loadCurrentURLInWebView]; |
| 1943 } | 1962 } |
| 1944 | 1963 |
| 1945 // Once a URL has been loaded, any cached-based reconstruction state has | 1964 // Once a URL has been loaded, any cached-based reconstruction state has |
| 1946 // either been handled or obsoleted. | 1965 // either been handled or obsoleted. |
| 1947 _expectedReconstructionURL = GURL(); | 1966 _expectedReconstructionURL = GURL(); |
| 1948 } | 1967 } |
| 1949 | 1968 |
| 1969 - (GURL)webURLWithTrustLevel:(web::URLVerificationTrustLevel*)trustLevel { |
| 1970 DCHECK(trustLevel); |
| 1971 *trustLevel = web::URLVerificationTrustLevel::kAbsolute; |
| 1972 return _documentURL; |
| 1973 } |
| 1974 |
| 1950 - (BOOL)shouldLoadURLInNativeView:(const GURL&)url { | 1975 - (BOOL)shouldLoadURLInNativeView:(const GURL&)url { |
| 1951 // App-specific URLs that don't require WebUI are loaded in native views. | 1976 // App-specific URLs that don't require WebUI are loaded in native views. |
| 1952 return web::GetWebClient()->IsAppSpecificURL(url) && | 1977 return web::GetWebClient()->IsAppSpecificURL(url) && |
| 1953 !_webStateImpl->HasWebUI(); | 1978 !_webStateImpl->HasWebUI(); |
| 1954 } | 1979 } |
| 1955 | 1980 |
| 1956 - (void)triggerPendingLoad { | 1981 - (void)triggerPendingLoad { |
| 1957 if (!self.containerView) { | 1982 if (!self.containerView) { |
| 1958 DCHECK(!_isBeingDestroyed); | 1983 DCHECK(!_isBeingDestroyed); |
| 1959 // Create the top-level parent view, which will contain the content (whether | 1984 // Create the top-level parent view, which will contain the content (whether |
| (...skipping 1193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3153 } | 3178 } |
| 3154 | 3179 |
| 3155 + (BOOL)webControllerCanShow:(const GURL&)url { | 3180 + (BOOL)webControllerCanShow:(const GURL&)url { |
| 3156 return web::UrlHasWebScheme(url) || | 3181 return web::UrlHasWebScheme(url) || |
| 3157 web::GetWebClient()->IsAppSpecificURL(url) || | 3182 web::GetWebClient()->IsAppSpecificURL(url) || |
| 3158 url.SchemeIs(url::kFileScheme) || url.SchemeIs(url::kAboutScheme); | 3183 url.SchemeIs(url::kFileScheme) || url.SchemeIs(url::kAboutScheme); |
| 3159 } | 3184 } |
| 3160 | 3185 |
| 3161 - (void)setUserInteractionRegistered:(BOOL)flag { | 3186 - (void)setUserInteractionRegistered:(BOOL)flag { |
| 3162 _userInteractionRegistered = flag; | 3187 _userInteractionRegistered = flag; |
| 3188 if (flag) |
| 3189 _interactionRegisteredSinceLastURLChange = YES; |
| 3163 } | 3190 } |
| 3164 | 3191 |
| 3165 - (BOOL)userInteractionRegistered { | 3192 - (BOOL)userInteractionRegistered { |
| 3166 return _userInteractionRegistered; | 3193 return _userInteractionRegistered; |
| 3167 } | 3194 } |
| 3168 | 3195 |
| 3169 - (BOOL)useDesktopUserAgent { | 3196 - (BOOL)useDesktopUserAgent { |
| 3170 web::NavigationItem* item = [self currentNavItem]; | 3197 web::NavigationItem* item = [self currentNavItem]; |
| 3171 return item && item->IsOverridingUserAgent(); | 3198 return item && item->IsOverridingUserAgent(); |
| 3172 } | 3199 } |
| (...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4369 return; | 4396 return; |
| 4370 } | 4397 } |
| 4371 | 4398 |
| 4372 if (!_SSLStatusUpdater) { | 4399 if (!_SSLStatusUpdater) { |
| 4373 _SSLStatusUpdater.reset([[CRWSSLStatusUpdater alloc] | 4400 _SSLStatusUpdater.reset([[CRWSSLStatusUpdater alloc] |
| 4374 initWithDataSource:self | 4401 initWithDataSource:self |
| 4375 navigationManager:navManager | 4402 navigationManager:navManager |
| 4376 certGroupID:self.certGroupID]); | 4403 certGroupID:self.certGroupID]); |
| 4377 [_SSLStatusUpdater setDelegate:self]; | 4404 [_SSLStatusUpdater setDelegate:self]; |
| 4378 } | 4405 } |
| 4379 NSString* host = base::SysUTF8ToNSString(self.documentURL.host()); | 4406 NSString* host = base::SysUTF8ToNSString(_documentURL.host()); |
| 4380 NSArray* certChain = [self.webView certificateChain]; | 4407 NSArray* certChain = [self.webView certificateChain]; |
| 4381 BOOL hasOnlySecureContent = [self.webView hasOnlySecureContent]; | 4408 BOOL hasOnlySecureContent = [self.webView hasOnlySecureContent]; |
| 4382 [_SSLStatusUpdater updateSSLStatusForNavigationItem:currentNavItem | 4409 [_SSLStatusUpdater updateSSLStatusForNavigationItem:currentNavItem |
| 4383 withCertHost:host | 4410 withCertHost:host |
| 4384 certChain:certChain | 4411 certChain:certChain |
| 4385 hasOnlySecureContent:hasOnlySecureContent]; | 4412 hasOnlySecureContent:hasOnlySecureContent]; |
| 4386 } | 4413 } |
| 4387 | 4414 |
| 4388 - (void)didUpdateSSLStatusForCurrentNavigationItem { | 4415 - (void)didUpdateSSLStatusForCurrentNavigationItem { |
| 4389 if ([_delegate respondsToSelector: | 4416 if ([_delegate respondsToSelector: |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4875 DCHECK_EQ(self.webView, webView); | 4902 DCHECK_EQ(self.webView, webView); |
| 4876 _certVerificationErrors->Clear(); | 4903 _certVerificationErrors->Clear(); |
| 4877 // This point should closely approximate the document object change, so reset | 4904 // This point should closely approximate the document object change, so reset |
| 4878 // the list of injected scripts to those that are automatically injected. | 4905 // the list of injected scripts to those that are automatically injected. |
| 4879 [self clearInjectedScriptManagers]; | 4906 [self clearInjectedScriptManagers]; |
| 4880 [self injectWindowID]; | 4907 [self injectWindowID]; |
| 4881 | 4908 |
| 4882 // This is the point where the document's URL has actually changed, and | 4909 // This is the point where the document's URL has actually changed, and |
| 4883 // pending navigation information should be applied to state information. | 4910 // pending navigation information should be applied to state information. |
| 4884 [self setDocumentURL:net::GURLWithNSURL([self.webView URL])]; | 4911 [self setDocumentURL:net::GURLWithNSURL([self.webView URL])]; |
| 4885 DCHECK(self.documentURL == self.lastRegisteredRequestURL); | 4912 DCHECK(_documentURL == self.lastRegisteredRequestURL); |
| 4886 self.webStateImpl->OnNavigationCommitted(self.documentURL); | 4913 self.webStateImpl->OnNavigationCommitted(_documentURL); |
| 4887 [self commitPendingNavigationInfo]; | 4914 [self commitPendingNavigationInfo]; |
| 4888 if ([self currentBackForwardListItemHolder]->navigation_type() == | 4915 if ([self currentBackForwardListItemHolder]->navigation_type() == |
| 4889 WKNavigationTypeBackForward) { | 4916 WKNavigationTypeBackForward) { |
| 4890 // A fast back/forward won't call decidePolicyForNavigationResponse, so | 4917 // A fast back/forward won't call decidePolicyForNavigationResponse, so |
| 4891 // the MIME type needs to be updated explicitly. | 4918 // the MIME type needs to be updated explicitly. |
| 4892 NSString* storedMIMEType = | 4919 NSString* storedMIMEType = |
| 4893 [self currentBackForwardListItemHolder]->mime_type(); | 4920 [self currentBackForwardListItemHolder]->mime_type(); |
| 4894 if (storedMIMEType) { | 4921 if (storedMIMEType) { |
| 4895 self.webStateImpl->SetContentsMimeType( | 4922 self.webStateImpl->SetContentsMimeType( |
| 4896 base::SysNSStringToUTF8(storedMIMEType)); | 4923 base::SysNSStringToUTF8(storedMIMEType)); |
| 4897 } | 4924 } |
| 4898 } | 4925 } |
| 4899 [self webPageChanged]; | 4926 [self webPageChanged]; |
| 4900 | 4927 |
| 4901 [self updateSSLStatusForCurrentNavigationItem]; | 4928 [self updateSSLStatusForCurrentNavigationItem]; |
| 4902 | 4929 |
| 4903 // Report cases where SSL cert is missing for a secure connection. | 4930 // Report cases where SSL cert is missing for a secure connection. |
| 4904 if (self.documentURL.SchemeIsCryptographic()) { | 4931 if (_documentURL.SchemeIsCryptographic()) { |
| 4905 scoped_refptr<net::X509Certificate> cert = | 4932 scoped_refptr<net::X509Certificate> cert = |
| 4906 web::CreateCertFromChain([self.webView certificateChain]); | 4933 web::CreateCertFromChain([self.webView certificateChain]); |
| 4907 UMA_HISTOGRAM_BOOLEAN("WebController.WKWebViewHasCertForSecureConnection", | 4934 UMA_HISTOGRAM_BOOLEAN("WebController.WKWebViewHasCertForSecureConnection", |
| 4908 cert); | 4935 cert); |
| 4909 } | 4936 } |
| 4910 } | 4937 } |
| 4911 | 4938 |
| 4912 - (void)webView:(WKWebView*)webView | 4939 - (void)webView:(WKWebView*)webView |
| 4913 didFinishNavigation:(WKNavigation*)navigation { | 4940 didFinishNavigation:(WKNavigation*)navigation { |
| 4914 DCHECK(!self.isHalted); | 4941 DCHECK(!self.isHalted); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5090 // could be a same-page navigation (in which case there may not be any other | 5117 // could be a same-page navigation (in which case there may not be any other |
| 5091 // callback about the URL having changed), then check the actual page URL via | 5118 // callback about the URL having changed), then check the actual page URL via |
| 5092 // JavaScript. If the origin of the new URL matches the last committed URL, | 5119 // JavaScript. If the origin of the new URL matches the last committed URL, |
| 5093 // then check window.location.href, and if it matches, trust it. The origin | 5120 // then check window.location.href, and if it matches, trust it. The origin |
| 5094 // check ensures that if a site somehow corrupts window.location.href it can't | 5121 // check ensures that if a site somehow corrupts window.location.href it can't |
| 5095 // do a redirect to a slow-loading target page while it is still loading to | 5122 // do a redirect to a slow-loading target page while it is still loading to |
| 5096 // spoof the origin. On a document-changing URL change, the | 5123 // spoof the origin. On a document-changing URL change, the |
| 5097 // window.location.href will match the previous URL at this stage, not the web | 5124 // window.location.href will match the previous URL at this stage, not the web |
| 5098 // view's current URL. | 5125 // view's current URL. |
| 5099 if (![self.webView isLoading]) { | 5126 if (![self.webView isLoading]) { |
| 5100 if (self.documentURL == URL) | 5127 if (_documentURL == URL) |
| 5101 return; | 5128 return; |
| 5102 [self URLDidChangeWithoutDocumentChange:URL]; | 5129 [self URLDidChangeWithoutDocumentChange:URL]; |
| 5103 } else if ([self isKVOChangePotentialSameDocumentNavigationToURL:URL]) { | 5130 } else if ([self isKVOChangePotentialSameDocumentNavigationToURL:URL]) { |
| 5104 [self.webView | 5131 [self.webView |
| 5105 evaluateJavaScript:@"window.location.href" | 5132 evaluateJavaScript:@"window.location.href" |
| 5106 completionHandler:^(id result, NSError* error) { | 5133 completionHandler:^(id result, NSError* error) { |
| 5107 // If the web view has gone away, or the location | 5134 // If the web view has gone away, or the location |
| 5108 // couldn't be retrieved, abort. | 5135 // couldn't be retrieved, abort. |
| 5109 if (!self.webView || ![result isKindOfClass:[NSString class]]) { | 5136 if (!self.webView || ![result isKindOfClass:[NSString class]]) { |
| 5110 return; | 5137 return; |
| 5111 } | 5138 } |
| 5112 GURL JSURL([result UTF8String]); | 5139 GURL JSURL([result UTF8String]); |
| 5113 // Check that window.location matches the new URL. If | 5140 // Check that window.location matches the new URL. If |
| 5114 // it does not, this is a document-changing URL change as | 5141 // it does not, this is a document-changing URL change as |
| 5115 // the window location would not have changed to the new | 5142 // the window location would not have changed to the new |
| 5116 // URL when the script was called. | 5143 // URL when the script was called. |
| 5117 BOOL windowLocationMatchesNewURL = JSURL == URL; | 5144 BOOL windowLocationMatchesNewURL = JSURL == URL; |
| 5118 // Re-check origin in case navigaton has occured since | 5145 // Re-check origin in case navigaton has occured since |
| 5119 // start of JavaScript evaluation. | 5146 // start of JavaScript evaluation. |
| 5120 BOOL newURLOriginMatchesDocumentURLOrigin = | 5147 BOOL newURLOriginMatchesDocumentURLOrigin = |
| 5121 self.documentURL.GetOrigin() == URL.GetOrigin(); | 5148 _documentURL.GetOrigin() == URL.GetOrigin(); |
| 5122 // Check that the web view URL still matches the new URL. | 5149 // Check that the web view URL still matches the new URL. |
| 5123 // TODO(crbug.com/563568): webViewURLMatchesNewURL check | 5150 // TODO(crbug.com/563568): webViewURLMatchesNewURL check |
| 5124 // may drop same document URL changes if pending URL | 5151 // may drop same document URL changes if pending URL |
| 5125 // change occurs immediately after. Revisit heuristics to | 5152 // change occurs immediately after. Revisit heuristics to |
| 5126 // prevent this. | 5153 // prevent this. |
| 5127 BOOL webViewURLMatchesNewURL = | 5154 BOOL webViewURLMatchesNewURL = |
| 5128 net::GURLWithNSURL([self.webView URL]) == URL; | 5155 net::GURLWithNSURL([self.webView URL]) == URL; |
| 5129 // Check that the new URL is different from the current | 5156 // Check that the new URL is different from the current |
| 5130 // document URL. If not, URL change should not be reported. | 5157 // document URL. If not, URL change should not be reported. |
| 5131 BOOL URLDidChangeFromDocumentURL = URL != self.documentURL; | 5158 BOOL URLDidChangeFromDocumentURL = URL != _documentURL; |
| 5132 if (windowLocationMatchesNewURL && | 5159 if (windowLocationMatchesNewURL && |
| 5133 newURLOriginMatchesDocumentURLOrigin && | 5160 newURLOriginMatchesDocumentURLOrigin && |
| 5134 webViewURLMatchesNewURL && URLDidChangeFromDocumentURL) { | 5161 webViewURLMatchesNewURL && URLDidChangeFromDocumentURL) { |
| 5135 [self URLDidChangeWithoutDocumentChange:URL]; | 5162 [self URLDidChangeWithoutDocumentChange:URL]; |
| 5136 } | 5163 } |
| 5137 }]; | 5164 }]; |
| 5138 } | 5165 } |
| 5139 } | 5166 } |
| 5140 | 5167 |
| 5141 - (BOOL)isKVOChangePotentialSameDocumentNavigationToURL:(const GURL&)newURL { | 5168 - (BOOL)isKVOChangePotentialSameDocumentNavigationToURL:(const GURL&)newURL { |
| 5142 DCHECK([self.webView isLoading]); | 5169 DCHECK([self.webView isLoading]); |
| 5143 // If the origin changes, it can't be same-document. | 5170 // If the origin changes, it can't be same-document. |
| 5144 if (self.documentURL.GetOrigin().is_empty() || | 5171 if (_documentURL.GetOrigin().is_empty() || |
| 5145 self.documentURL.GetOrigin() != newURL.GetOrigin()) { | 5172 _documentURL.GetOrigin() != newURL.GetOrigin()) { |
| 5146 return NO; | 5173 return NO; |
| 5147 } | 5174 } |
| 5148 if (self.loadPhase == web::LOAD_REQUESTED) { | 5175 if (self.loadPhase == web::LOAD_REQUESTED) { |
| 5149 // Normally LOAD_REQUESTED indicates that this is a regular, pending | 5176 // Normally LOAD_REQUESTED indicates that this is a regular, pending |
| 5150 // navigation, but it can also happen during a fast-back navigation across | 5177 // navigation, but it can also happen during a fast-back navigation across |
| 5151 // a hash change, so that case is potentially a same-document navigation. | 5178 // a hash change, so that case is potentially a same-document navigation. |
| 5152 return web::GURLByRemovingRefFromGURL(newURL) == | 5179 return web::GURLByRemovingRefFromGURL(newURL) == |
| 5153 web::GURLByRemovingRefFromGURL(self.documentURL); | 5180 web::GURLByRemovingRefFromGURL(_documentURL); |
| 5154 } | 5181 } |
| 5155 // If it passes all the checks above, it might be (but there's no guarantee | 5182 // If it passes all the checks above, it might be (but there's no guarantee |
| 5156 // that it is). | 5183 // that it is). |
| 5157 return YES; | 5184 return YES; |
| 5158 } | 5185 } |
| 5159 | 5186 |
| 5160 - (void)URLDidChangeWithoutDocumentChange:(const GURL&)newURL { | 5187 - (void)URLDidChangeWithoutDocumentChange:(const GURL&)newURL { |
| 5161 DCHECK(newURL == net::GURLWithNSURL([self.webView URL])); | 5188 DCHECK(newURL == net::GURLWithNSURL([self.webView URL])); |
| 5162 DCHECK_EQ(self.documentURL.host(), newURL.host()); | 5189 DCHECK_EQ(_documentURL.host(), newURL.host()); |
| 5163 DCHECK(self.documentURL != newURL); | 5190 DCHECK(_documentURL != newURL); |
| 5164 | 5191 |
| 5165 // If called during window.history.pushState or window.history.replaceState | 5192 // If called during window.history.pushState or window.history.replaceState |
| 5166 // JavaScript evaluation, only update the document URL. This callback does not | 5193 // JavaScript evaluation, only update the document URL. This callback does not |
| 5167 // have any information about the state object and cannot create (or edit) the | 5194 // have any information about the state object and cannot create (or edit) the |
| 5168 // navigation entry for this page change. Web controller will sync with | 5195 // navigation entry for this page change. Web controller will sync with |
| 5169 // history changes when a window.history.didPushState or | 5196 // history changes when a window.history.didPushState or |
| 5170 // window.history.didReplaceState message is received, which should happen in | 5197 // window.history.didReplaceState message is received, which should happen in |
| 5171 // the next runloop. | 5198 // the next runloop. |
| 5172 // | 5199 // |
| 5173 // Otherwise, simulate the whole delegate flow for a load (since the | 5200 // Otherwise, simulate the whole delegate flow for a load (since the |
| 5174 // superclass currently doesn't have a clean separation between URL changes | 5201 // superclass currently doesn't have a clean separation between URL changes |
| 5175 // and document changes). Note that the order of these calls is important: | 5202 // and document changes). Note that the order of these calls is important: |
| 5176 // registering a load request logically comes before updating the document | 5203 // registering a load request logically comes before updating the document |
| 5177 // URL, but also must come first since it uses state that is reset on URL | 5204 // URL, but also must come first since it uses state that is reset on URL |
| 5178 // changes. | 5205 // changes. |
| 5179 if (!self.changingHistoryState) { | 5206 if (!self.changingHistoryState) { |
| 5180 // If this wasn't a previously-expected load (e.g., certain back/forward | 5207 // If this wasn't a previously-expected load (e.g., certain back/forward |
| 5181 // navigations), register the load request. | 5208 // navigations), register the load request. |
| 5182 if (![self isLoadRequestPendingForURL:newURL]) | 5209 if (![self isLoadRequestPendingForURL:newURL]) |
| 5183 [self registerLoadRequest:newURL]; | 5210 [self registerLoadRequest:newURL]; |
| 5184 } | 5211 } |
| 5185 | 5212 |
| 5186 [self setDocumentURL:newURL]; | 5213 [self setDocumentURL:newURL]; |
| 5187 | 5214 |
| 5188 if (!self.changingHistoryState) { | 5215 if (!self.changingHistoryState) { |
| 5189 [self didStartLoadingURL:self.documentURL updateHistory:YES]; | 5216 [self didStartLoadingURL:_documentURL updateHistory:YES]; |
| 5190 [self updateSSLStatusForCurrentNavigationItem]; | 5217 [self updateSSLStatusForCurrentNavigationItem]; |
| 5191 [self didFinishNavigation]; | 5218 [self didFinishNavigation]; |
| 5192 } | 5219 } |
| 5193 } | 5220 } |
| 5194 | 5221 |
| 5195 - (BOOL)isLoadRequestPendingForURL:(const GURL&)targetURL { | 5222 - (BOOL)isLoadRequestPendingForURL:(const GURL&)targetURL { |
| 5196 if (self.loadPhase != web::LOAD_REQUESTED) | 5223 if (self.loadPhase != web::LOAD_REQUESTED) |
| 5197 return NO; | 5224 return NO; |
| 5198 | 5225 |
| 5199 web::NavigationItem* pendingItem = | 5226 web::NavigationItem* pendingItem = |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5314 } | 5341 } |
| 5315 | 5342 |
| 5316 return web::WEB_VIEW_DOCUMENT_TYPE_GENERIC; | 5343 return web::WEB_VIEW_DOCUMENT_TYPE_GENERIC; |
| 5317 } | 5344 } |
| 5318 | 5345 |
| 5319 - (NSString*)refererFromNavigationAction:(WKNavigationAction*)action { | 5346 - (NSString*)refererFromNavigationAction:(WKNavigationAction*)action { |
| 5320 return [action.request valueForHTTPHeaderField:@"Referer"]; | 5347 return [action.request valueForHTTPHeaderField:@"Referer"]; |
| 5321 } | 5348 } |
| 5322 | 5349 |
| 5323 @end | 5350 @end |
| OLD | NEW |