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

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

Issue 1322193003: WKWebView(iOS9): correctly update SSL status for current navigation item (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@reland_cert_verification
Patch Set: Do not use CertVerifier for good certs Created 5 years, 2 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
OLDNEW
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/ios/ios_util.h" 9 #include "base/ios/ios_util.h"
10 #include "base/ios/weak_nsobject.h" 10 #include "base/ios/weak_nsobject.h"
11 #include "base/json/json_reader.h" 11 #include "base/json/json_reader.h"
12 #import "base/mac/scoped_nsobject.h" 12 #import "base/mac/scoped_nsobject.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/sys_string_conversions.h" 15 #include "base/strings/sys_string_conversions.h"
15 #include "base/values.h" 16 #include "base/values.h"
16 #import "ios/net/http_response_headers_util.h" 17 #import "ios/net/http_response_headers_util.h"
17 #import "ios/web/crw_network_activity_indicator_manager.h" 18 #import "ios/web/crw_network_activity_indicator_manager.h"
18 #import "ios/web/navigation/crw_session_controller.h" 19 #import "ios/web/navigation/crw_session_controller.h"
19 #import "ios/web/navigation/crw_session_entry.h" 20 #import "ios/web/navigation/crw_session_entry.h"
20 #include "ios/web/navigation/navigation_item_impl.h" 21 #include "ios/web/navigation/navigation_item_impl.h"
21 #include "ios/web/navigation/web_load_params.h" 22 #include "ios/web/navigation/web_load_params.h"
22 #import "ios/web/net/crw_cert_verification_controller.h" 23 #import "ios/web/net/crw_cert_verification_controller.h"
23 #include "ios/web/public/cert_store.h" 24 #include "ios/web/public/cert_store.h"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 userInfo:userInfo]; 76 userInfo:userInfo];
76 } 77 }
77 WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { 78 WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
78 DCHECK(error); 79 DCHECK(error);
79 return static_cast<WKWebViewErrorSource>( 80 return static_cast<WKWebViewErrorSource>(
80 [error.userInfo[kWKWebViewErrorSourceKey] integerValue]); 81 [error.userInfo[kWKWebViewErrorSourceKey] integerValue]);
81 } 82 }
82 83
83 } // namespace 84 } // namespace
84 85
86 #if !defined(__IPHONE_9_0)
87 // Predeclare iOS9 API so calls are compiled on iOS8 bots.
88 // TODO(eugenebut): cleanup this (crbug.com/523365).
89 @interface WKWebView (CRWIOS9API)
90 @property(nonatomic, readonly, copy) NSArray* certificateChain;
91 @end
92 #endif
93
85 @interface CRWWKWebViewWebController () <WKNavigationDelegate, 94 @interface CRWWKWebViewWebController () <WKNavigationDelegate,
86 WKScriptMessageHandler, 95 WKScriptMessageHandler,
87 WKUIDelegate> { 96 WKUIDelegate> {
88 // The WKWebView managed by this instance. 97 // The WKWebView managed by this instance.
89 base::scoped_nsobject<WKWebView> _wkWebView; 98 base::scoped_nsobject<WKWebView> _wkWebView;
90 99
91 // The Watch Dog that detects and reports WKWebView crashes. 100 // The Watch Dog that detects and reports WKWebView crashes.
92 base::scoped_nsobject<CRWWKWebViewCrashDetector> _crashDetector; 101 base::scoped_nsobject<CRWWKWebViewCrashDetector> _crashDetector;
93 102
94 // The actual URL of the document object (i.e., the last committed URL). 103 // The actual URL of the document object (i.e., the last committed URL).
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 // Called when a load ends in an SSL error. 252 // Called when a load ends in an SSL error.
244 - (void)handleSSLError:(NSError*)error; 253 - (void)handleSSLError:(NSError*)error;
245 #endif 254 #endif
246 255
247 // Adds an activity indicator tasks for this web controller. 256 // Adds an activity indicator tasks for this web controller.
248 - (void)addActivityIndicatorTask; 257 - (void)addActivityIndicatorTask;
249 258
250 // Clears all activity indicator tasks for this web controller. 259 // Clears all activity indicator tasks for this web controller.
251 - (void)clearActivityIndicatorTasks; 260 - (void)clearActivityIndicatorTasks;
252 261
262 // Obtains SSL status from given |certChain| and updates navigation items with
263 // given |certID| and |host|.
264 - (void)updateSSLStatusForNavigationItemsWithCertID:(int)certID
265 host:(NSString*)host
266 usingCertChain:(NSArray*)certChain;
267
253 #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) 268 #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW)
254 // Updates SSL status for the current navigation item based on the information 269 // Updates SSL status for the current navigation item based on the information
255 // provided by web view. 270 // provided by web view.
256 - (void)updateSSLStatusForCurrentNavigationItem; 271 - (void)updateSSLStatusForCurrentNavigationItem;
257 #endif 272 #endif
258 273
259 // Registers load request with empty referrer and link or client redirect 274 // Registers load request with empty referrer and link or client redirect
260 // transition based on user interaction state. 275 // transition based on user interaction state.
261 - (void)registerLoadRequest:(const GURL&)url; 276 - (void)registerLoadRequest:(const GURL&)url;
262 277
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 - (void)addActivityIndicatorTask { 872 - (void)addActivityIndicatorTask {
858 [[CRWNetworkActivityIndicatorManager sharedInstance] 873 [[CRWNetworkActivityIndicatorManager sharedInstance]
859 startNetworkTaskForGroup:[self activityIndicatorGroupID]]; 874 startNetworkTaskForGroup:[self activityIndicatorGroupID]];
860 } 875 }
861 876
862 - (void)clearActivityIndicatorTasks { 877 - (void)clearActivityIndicatorTasks {
863 [[CRWNetworkActivityIndicatorManager sharedInstance] 878 [[CRWNetworkActivityIndicatorManager sharedInstance]
864 clearNetworkTasksForGroup:[self activityIndicatorGroupID]]; 879 clearNetworkTasksForGroup:[self activityIndicatorGroupID]];
865 } 880 }
866 881
882 - (void)updateSSLStatusForNavigationItemsWithCertID:(int)certID
davidben 2015/10/05 22:19:11 Yikes. What exactly do you all use cert IDs for? I
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 Fetching CertStatus is asynchronous operation, so
stuartmorgan 2015/10/06 22:02:36 Per offline discussion, let's have the navigation
Eugene But (OOO till 7-30) 2015/10/07 15:27:13 Done.
davidben 2015/10/07 20:16:29 Oh, actually, I'd missed that you don't use conten
Eugene But (OOO till 7-30) 2015/10/08 16:53:32 We want to keep web::SSLStatus as close as possibl
883 host:(NSString*)host
884 usingCertChain:(NSArray*)certChain {
885 base::WeakNSObject<CRWWKWebViewWebController> weakSelf(self);
886 void (^SSLStatusResponse)(web::SecurityStyle, net::CertStatus) = ^(
887 web::SecurityStyle style, net::CertStatus certStatus) {
888 base::scoped_nsobject<CRWWKWebViewWebController> strongSelf(
889 [weakSelf retain]);
890 if (!strongSelf || [strongSelf isBeingDestroyed]) {
891 return;
892 }
893
894 web::NavigationManager* navigationManager =
895 [strongSelf webStateImpl]->GetNavigationManager();
896 int currentItemIndex = navigationManager->GetCurrentEntryIndex();
897
898 bool updatedCurrentItem = false;
899 std::string GURLHost = base::SysNSStringToUTF8(host);
900 for (int i = 0; i < navigationManager->GetEntryCount(); i++) {
901 web::NavigationItem* item = navigationManager->GetItemAtIndex(i);
902 web::SSLStatus& SSLStatus = item->GetSSL();
903 if (SSLStatus.cert_id == certID && item->GetURL().host() == GURLHost) {
904 web::SSLStatus previousSSLStatus = item->GetSSL();
905 SSLStatus.cert_status = certStatus;
906 SSLStatus.security_style = style;
907 if (currentItemIndex == i && !previousSSLStatus.Equals(SSLStatus)) {
908 updatedCurrentItem = true;
909 }
910 }
911 }
912
913 if (updatedCurrentItem) {
914 [strongSelf didUpdateSSLStatusForCurrentNavigationItem];
915 }
916 };
917
918 [_certVerificationController
919 querySSLStatusForTrust:web::CreateServerTrustFromChain(certChain, host)
920 host:host
921 completionHandler:SSLStatusResponse];
922 }
923
867 #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) 924 #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW)
925
868 - (void)updateSSLStatusForCurrentNavigationItem { 926 - (void)updateSSLStatusForCurrentNavigationItem {
869 if ([self isBeingDestroyed]) 927 if ([self isBeingDestroyed])
870 return; 928 return;
871 929
872 DCHECK(self.webStateImpl);
873 web::NavigationItem* item = 930 web::NavigationItem* item =
874 self.webStateImpl->GetNavigationManagerImpl().GetLastCommittedItem(); 931 self.webStateImpl->GetNavigationManagerImpl().GetLastCommittedItem();
875 if (!item) 932 if (!item)
876 return; 933 return;
877 934
878 web::SSLStatus previousSSLStatus = item->GetSSL(); 935 web::SSLStatus previousSSLStatus = item->GetSSL();
879 web::SSLStatus& SSLStatus = item->GetSSL(); 936 web::SSLStatus& SSLStatus = item->GetSSL();
880 if (item->GetURL().SchemeIsCryptographic()) {
881 // TODO(eugenebut): Do not set security style to authenticated once
882 // proceeding with bad ssl cert is implemented.
883 SSLStatus.security_style = web::SECURITY_STYLE_AUTHENTICATED;
884 SSLStatus.content_status = [_wkWebView hasOnlySecureContent]
885 ? web::SSLStatus::NORMAL_CONTENT
886 : web::SSLStatus::DISPLAYED_INSECURE_CONTENT;
887 937
888 if (base::ios::IsRunningOnIOS9OrLater()) { 938 // Starting from iOS9 WKWebView blocks active mixed content, so if
889 scoped_refptr<net::X509Certificate> cert(web::CreateCertFromChain( 939 // |hasOnlySecureContent| returns NO it means passive content.
890 [_wkWebView performSelector:@selector(certificateChain)])); 940 // On iOS8 there is no way to determine if web view has active mixed content.
891 if (cert) { 941 SSLStatus.content_status = [_wkWebView hasOnlySecureContent]
892 SSLStatus.cert_id = web::CertStore::GetInstance()->StoreCert( 942 ? web::SSLStatus::NORMAL_CONTENT
893 cert.get(), self.certGroupID); 943 : web::SSLStatus::DISPLAYED_INSECURE_CONTENT;
894 } else { 944
895 SSLStatus.security_style = web::SECURITY_STYLE_UNAUTHENTICATED; 945 // Retrieve top level frame certificate.
896 SSLStatus.cert_id = 0; 946 scoped_refptr<net::X509Certificate> cert;
947 if (base::ios::IsRunningOnIOS9OrLater() &&
948 item->GetURL().SchemeIsCryptographic()) {
949 NSArray* chain = [_wkWebView certificateChain];
950 cert = web::CreateCertFromChain(chain);
951 if (cert) {
952 UMA_HISTOGRAM_BOOLEAN("WebController.WKWebViewHasCertForSecureConnection",
953 true);
954 int oldCertID = SSLStatus.cert_id;
955 SSLStatus.cert_id = web::CertStore::GetInstance()->StoreCert(
956 cert.get(), self.certGroupID);
957 NSString* host = [_wkWebView URL].host;
958 if (oldCertID != SSLStatus.cert_id ||
davidben 2015/10/05 22:19:11 I don't believe this can ever be false. Looking at
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 This can be false and w/o this check cert status w
davidben 2015/10/07 20:16:29 Ah, you're right. I'd missed that.
959 item->GetURL().host() != base::SysNSStringToUTF8(host)) {
960 [self updateSSLStatusForNavigationItemsWithCertID:SSLStatus.cert_id
961 host:host
962 usingCertChain:chain];
davidben 2015/10/05 22:19:11 Why update all navigation entries? This is confusi
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 Replied above. I did not find a good way to find c
Eugene But (OOO till 7-30) 2015/10/07 15:27:13 Actually there is a way to update only requested e
897 } 963 }
898 } 964 }
899 } else { 965 }
900 SSLStatus.security_style = web::SECURITY_STYLE_UNAUTHENTICATED; 966
967 if (!cert) {
901 SSLStatus.cert_id = 0; 968 SSLStatus.cert_id = 0;
969 if (!item->GetURL().SchemeIsCryptographic()) {
970 // HTTP or other non-secure connection.
971 SSLStatus.security_style = web::SECURITY_STYLE_UNAUTHENTICATED;
972 } else if (base::ios::IsRunningOnIOS9OrLater()) {
973 // HTTPS, iOS9 and no certificate (this use-case has not been observed).
974 UMA_HISTOGRAM_BOOLEAN("WebController.WKWebViewHasCertForSecureConnection",
975 false);
davidben 2015/10/05 22:19:11 UMA_HISTOGRAM macros expand to a fair amount of co
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 Moved to a separate function.
976 SSLStatus.security_style = web::SECURITY_STYLE_UNKNOWN;
977 } else {
978 // HTTPS, iOS8.
979 // iOS8 cannot load unauthenticated HTTPS content.
980 SSLStatus.security_style = web::SECURITY_STYLE_AUTHENTICATED;
981 }
902 } 982 }
903 983
904 if (!previousSSLStatus.Equals(SSLStatus)) { 984 if (!previousSSLStatus.Equals(SSLStatus)) {
905 [self didUpdateSSLStatusForCurrentNavigationItem]; 985 [self didUpdateSSLStatusForCurrentNavigationItem];
906 } 986 }
907 } 987 }
988
908 #endif // !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) 989 #endif // !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW)
909 990
910 - (void)registerLoadRequest:(const GURL&)url { 991 - (void)registerLoadRequest:(const GURL&)url {
911 // If load request is registered via WKWebViewWebController, assume transition 992 // If load request is registered via WKWebViewWebController, assume transition
912 // is link or client redirect as other transitions will already be registered 993 // is link or client redirect as other transitions will already be registered
913 // by web controller or delegates. 994 // by web controller or delegates.
914 // TODO(stuartmorgan): Remove guesswork and replace with information from 995 // TODO(stuartmorgan): Remove guesswork and replace with information from
915 // decidePolicyForNavigationAction:. 996 // decidePolicyForNavigationAction:.
916 ui::PageTransition transition = self.userInteractionRegistered 997 ui::PageTransition transition = self.userInteractionRegistered
917 ? ui::PAGE_TRANSITION_LINK 998 ? ui::PAGE_TRANSITION_LINK
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
1486 placeholderText:defaultText 1567 placeholderText:defaultText
1487 requestURL: 1568 requestURL:
1488 net::GURLWithNSURL(frame.request.URL) 1569 net::GURLWithNSURL(frame.request.URL)
1489 completionHandler:completionHandler]; 1570 completionHandler:completionHandler];
1490 } else if (completionHandler) { 1571 } else if (completionHandler) {
1491 completionHandler(nil); 1572 completionHandler(nil);
1492 } 1573 }
1493 } 1574 }
1494 1575
1495 @end 1576 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698