| 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 <WebKit/WebKit.h> | 7 #import <WebKit/WebKit.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 using web::NavigationManagerImpl; | 49 using web::NavigationManagerImpl; |
| 50 | 50 |
| 51 @interface CRWWebController (PrivateAPI) | 51 @interface CRWWebController (PrivateAPI) |
| 52 @property(nonatomic, readwrite) web::PageDisplayState pageDisplayState; | 52 @property(nonatomic, readwrite) web::PageDisplayState pageDisplayState; |
| 53 - (GURL)URLForHistoryNavigationFromItem:(web::NavigationItem*)fromItem | 53 - (GURL)URLForHistoryNavigationFromItem:(web::NavigationItem*)fromItem |
| 54 toItem:(web::NavigationItem*)toItem; | 54 toItem:(web::NavigationItem*)toItem; |
| 55 @end | 55 @end |
| 56 | 56 |
| 57 // Used to mock CRWWebDelegate methods with C++ params. | 57 // Used to mock CRWWebDelegate methods with C++ params. |
| 58 @interface MockInteractionLoader : OCMockComplexTypeHelper | 58 @interface MockInteractionLoader : OCMockComplexTypeHelper |
| 59 // Whether or not the delegate should block popups. | |
| 60 @property(nonatomic, assign) BOOL blockPopups; | |
| 61 // A web controller that will be returned by webPageOrdered... methods. | |
| 62 @property(nonatomic, assign) CRWWebController* childWebController; | |
| 63 | |
| 64 // Values of arguments passed to | |
| 65 // |webController:createWebControllerForURL:openerURL:initiatedByUser:|. | |
| 66 @property(nonatomic, readonly) CRWWebController* webController; | |
| 67 @property(nonatomic, readonly) GURL childURL; | |
| 68 @property(nonatomic, readonly) GURL openerURL; | |
| 69 @property(nonatomic, readonly) BOOL initiatedByUser; | |
| 70 @end | 59 @end |
| 71 | 60 |
| 72 @implementation MockInteractionLoader | 61 @implementation MockInteractionLoader |
| 73 | 62 |
| 74 @synthesize blockPopups = _blockPopups; | |
| 75 @synthesize childWebController = _childWebController; | |
| 76 @synthesize webController = _webController; | |
| 77 @synthesize childURL = _childURL; | |
| 78 @synthesize openerURL = _openerURL; | |
| 79 @synthesize initiatedByUser = _initiatedByUser; | |
| 80 | |
| 81 - (instancetype)initWithRepresentedObject:(id)representedObject { | |
| 82 self = [super initWithRepresentedObject:representedObject]; | |
| 83 if (self) { | |
| 84 _blockPopups = YES; | |
| 85 } | |
| 86 return self; | |
| 87 } | |
| 88 | |
| 89 - (CRWWebController*)webController:(CRWWebController*)webController | |
| 90 createWebControllerForURL:(const GURL&)childURL | |
| 91 openerURL:(const GURL&)openerURL | |
| 92 initiatedByUser:(BOOL)initiatedByUser { | |
| 93 _webController = webController; | |
| 94 _childURL = childURL; | |
| 95 _openerURL = openerURL; | |
| 96 _initiatedByUser = initiatedByUser; | |
| 97 | |
| 98 return (_blockPopups && !initiatedByUser) ? nil : _childWebController; | |
| 99 } | |
| 100 | |
| 101 typedef BOOL (^openExternalURLBlockType)(const GURL&); | 63 typedef BOOL (^openExternalURLBlockType)(const GURL&); |
| 102 | 64 |
| 103 - (BOOL)openExternalURL:(const GURL&)url { | 65 - (BOOL)openExternalURL:(const GURL&)url { |
| 104 return static_cast<openExternalURLBlockType>([self blockForSelector:_cmd])( | 66 return static_cast<openExternalURLBlockType>([self blockForSelector:_cmd])( |
| 105 url); | 67 url); |
| 106 } | 68 } |
| 107 | 69 |
| 108 - (BOOL)webController:(CRWWebController*)webController | 70 - (BOOL)webController:(CRWWebController*)webController |
| 109 shouldOpenURL:(const GURL&)URL | 71 shouldOpenURL:(const GURL&)URL |
| 110 mainDocumentURL:(const GURL&)mainDocumentURL | 72 mainDocumentURL:(const GURL&)mainDocumentURL |
| (...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 [web_controller() webStateImpl]->OnPageLoaded(GURL("http://test"), false); | 840 [web_controller() webStateImpl]->OnPageLoaded(GURL("http://test"), false); |
| 879 EXPECT_EQ(0, [observer pageLoadedCount]); | 841 EXPECT_EQ(0, [observer pageLoadedCount]); |
| 880 [web_controller() webStateImpl]->OnPageLoaded(GURL("http://test"), true); | 842 [web_controller() webStateImpl]->OnPageLoaded(GURL("http://test"), true); |
| 881 EXPECT_EQ(1, [observer pageLoadedCount]); | 843 EXPECT_EQ(1, [observer pageLoadedCount]); |
| 882 | 844 |
| 883 [web_controller() removeObserver:observer]; | 845 [web_controller() removeObserver:observer]; |
| 884 EXPECT_EQ(0u, [web_controller() observerCount]); | 846 EXPECT_EQ(0u, [web_controller() observerCount]); |
| 885 }; | 847 }; |
| 886 | 848 |
| 887 // Test fixture for window.open tests. | 849 // Test fixture for window.open tests. |
| 888 class CRWWebControllerWindowOpenTest : public web::WebTestWithWebController { | 850 class WindowOpenByDomTest : public web::WebTestWithWebController { |
| 889 protected: | 851 protected: |
| 852 WindowOpenByDomTest() : opener_url_("http://test") {} |
| 853 |
| 890 void SetUp() override { | 854 void SetUp() override { |
| 891 web::WebTestWithWebController::SetUp(); | 855 WebTestWithWebController::SetUp(); |
| 892 | 856 web_state()->SetDelegate(&delegate_); |
| 893 // Configure web delegate. | 857 LoadHtml(@"<html><body></body></html>", opener_url_); |
| 894 delegate_.reset([[MockInteractionLoader alloc] | |
| 895 initWithRepresentedObject: | |
| 896 [OCMockObject niceMockForProtocol:@protocol(CRWWebDelegate)]]); | |
| 897 ASSERT_TRUE([delegate_ blockPopups]); | |
| 898 [web_controller() setDelegate:delegate_]; | |
| 899 | |
| 900 // Configure child web state. | |
| 901 child_web_state_.reset(new web::WebStateImpl(GetBrowserState())); | |
| 902 child_web_state_->SetWebUsageEnabled(true); | |
| 903 [delegate_ setChildWebController:child_web_state_->GetWebController()]; | |
| 904 | |
| 905 // Configure child web controller's session controller mock. | |
| 906 id sessionController = | |
| 907 [OCMockObject niceMockForClass:[CRWSessionController class]]; | |
| 908 BOOL yes = YES; | |
| 909 [[[sessionController stub] andReturnValue:OCMOCK_VALUE(yes)] isOpenedByDOM]; | |
| 910 child_web_state_->GetNavigationManagerImpl().SetSessionController( | |
| 911 sessionController); | |
| 912 | |
| 913 LoadHtml(@"<html><body></body></html>", GURL("http://test")); | |
| 914 } | |
| 915 void TearDown() override { | |
| 916 EXPECT_OCMOCK_VERIFY(delegate_); | |
| 917 [web_controller() setDelegate:nil]; | |
| 918 | |
| 919 web::WebTestWithWebController::TearDown(); | |
| 920 } | 858 } |
| 921 // Executes JavaScript that opens a new window and returns evaluation result | 859 // Executes JavaScript that opens a new window and returns evaluation result |
| 922 // as a string. | 860 // as a string. |
| 923 id OpenWindowByDOM() { | 861 id OpenWindowByDom() { |
| 924 NSString* const kOpenWindowScript = | 862 NSString* const kOpenWindowScript = |
| 925 @"var w = window.open('javascript:void(0);', target='_blank');" | 863 @"var w = window.open('javascript:void(0);', target='_blank');" |
| 926 "w ? w.toString() : null;"; | 864 "w ? w.toString() : null;"; |
| 927 id windowJSObject = ExecuteJavaScript(kOpenWindowScript); | 865 id windowJSObject = ExecuteJavaScript(kOpenWindowScript); |
| 928 WaitForBackgroundTasks(); | 866 WaitForBackgroundTasks(); |
| 929 return windowJSObject; | 867 return windowJSObject; |
| 930 } | 868 } |
| 931 // A CRWWebDelegate mock used for testing. | 869 // URL of a page which opens child windows. |
| 932 base::scoped_nsobject<id> delegate_; | 870 const GURL opener_url_; |
| 933 // A child WebState used for testing. | 871 web::TestWebStateDelegate delegate_; |
| 934 std::unique_ptr<web::WebStateImpl> child_web_state_; | |
| 935 }; | 872 }; |
| 936 | 873 |
| 937 // Tests that absence of web delegate is handled gracefully. | 874 // Tests that absence of web state delegate is handled gracefully. |
| 938 TEST_F(CRWWebControllerWindowOpenTest, NoDelegate) { | 875 TEST_F(WindowOpenByDomTest, NoDelegate) { |
| 939 [web_controller() setDelegate:nil]; | 876 web_state()->SetDelegate(nullptr); |
| 940 | 877 |
| 941 EXPECT_NSEQ([NSNull null], OpenWindowByDOM()); | 878 EXPECT_NSEQ([NSNull null], OpenWindowByDom()); |
| 942 | 879 |
| 943 EXPECT_FALSE([delegate_ webController]); | 880 EXPECT_TRUE(delegate_.child_windows().empty()); |
| 944 EXPECT_FALSE([delegate_ childURL].is_valid()); | 881 EXPECT_TRUE(delegate_.popups().empty()); |
| 945 EXPECT_FALSE([delegate_ openerURL].is_valid()); | |
| 946 EXPECT_FALSE([delegate_ initiatedByUser]); | |
| 947 } | 882 } |
| 948 | 883 |
| 949 // Tests that window.open triggered by user gesture opens a new non-popup | 884 // Tests that window.open triggered by user gesture opens a new non-popup |
| 950 // window. | 885 // window. |
| 951 TEST_F(CRWWebControllerWindowOpenTest, OpenWithUserGesture) { | 886 TEST_F(WindowOpenByDomTest, OpenWithUserGesture) { |
| 952 [web_controller() touched:YES]; | 887 [web_controller() touched:YES]; |
| 953 EXPECT_NSEQ(@"[object Window]", OpenWindowByDOM()); | 888 EXPECT_NSEQ(@"[object Window]", OpenWindowByDom()); |
| 954 | 889 |
| 955 EXPECT_EQ(web_controller(), [delegate_ webController]); | 890 ASSERT_EQ(1U, delegate_.child_windows().size()); |
| 956 EXPECT_EQ("javascript:void(0);", [delegate_ childURL].spec()); | 891 ASSERT_TRUE(delegate_.child_windows()[0]); |
| 957 EXPECT_EQ("http://test/", [delegate_ openerURL].spec()); | 892 EXPECT_TRUE(delegate_.popups().empty()); |
| 958 EXPECT_TRUE([delegate_ initiatedByUser]); | |
| 959 } | 893 } |
| 960 | 894 |
| 961 // Tests that window.open executed w/o user gesture does not open a new window. | 895 // Tests that window.open executed w/o user gesture does not open a new window, |
| 962 // Once the blocked popup is allowed a new window is opened. | 896 // but blocks popup instead. |
| 963 TEST_F(CRWWebControllerWindowOpenTest, AllowPopup) { | 897 TEST_F(WindowOpenByDomTest, BlockPopup) { |
| 964 ASSERT_FALSE([web_controller() userIsInteracting]); | 898 ASSERT_FALSE([web_controller() userIsInteracting]); |
| 965 EXPECT_NSEQ([NSNull null], OpenWindowByDOM()); | 899 EXPECT_NSEQ([NSNull null], OpenWindowByDom()); |
| 966 | 900 |
| 967 EXPECT_EQ(web_controller(), [delegate_ webController]); | 901 EXPECT_TRUE(delegate_.child_windows().empty()); |
| 968 EXPECT_EQ("javascript:void(0);", [delegate_ childURL].spec()); | 902 ASSERT_EQ(1U, delegate_.popups().size()); |
| 969 EXPECT_EQ("http://test/", [delegate_ openerURL].spec()); | 903 EXPECT_EQ(GURL("javascript:void(0);"), delegate_.popups()[0].url); |
| 970 EXPECT_FALSE([delegate_ initiatedByUser]); | 904 EXPECT_EQ(opener_url_, delegate_.popups()[0].opener_url); |
| 971 } | 905 } |
| 972 | 906 |
| 973 // Tests that window.open executed w/o user gesture opens a new window, assuming | 907 // Tests that window.open executed w/o user gesture opens a new window, assuming |
| 974 // that delegate allows popups. | 908 // that delegate allows popups. |
| 975 TEST_F(CRWWebControllerWindowOpenTest, DontBlockPopup) { | 909 TEST_F(WindowOpenByDomTest, DontBlockPopup) { |
| 976 [delegate_ setBlockPopups:NO]; | 910 delegate_.allow_popups(opener_url_); |
| 977 EXPECT_NSEQ(@"[object Window]", OpenWindowByDOM()); | 911 EXPECT_NSEQ(@"[object Window]", OpenWindowByDom()); |
| 978 | 912 |
| 979 EXPECT_EQ(web_controller(), [delegate_ webController]); | 913 ASSERT_EQ(1U, delegate_.child_windows().size()); |
| 980 EXPECT_EQ("javascript:void(0);", [delegate_ childURL].spec()); | 914 ASSERT_TRUE(delegate_.child_windows()[0]); |
| 981 EXPECT_EQ("http://test/", [delegate_ openerURL].spec()); | 915 EXPECT_TRUE(delegate_.popups().empty()); |
| 982 EXPECT_FALSE([delegate_ initiatedByUser]); | |
| 983 } | 916 } |
| 984 | 917 |
| 985 // Tests that window.open executed w/o user gesture does not open a new window. | |
| 986 TEST_F(CRWWebControllerWindowOpenTest, BlockPopup) { | |
| 987 ASSERT_FALSE([web_controller() userIsInteracting]); | |
| 988 EXPECT_NSEQ([NSNull null], OpenWindowByDOM()); | |
| 989 | |
| 990 EXPECT_EQ(web_controller(), [delegate_ webController]); | |
| 991 EXPECT_EQ("javascript:void(0);", [delegate_ childURL].spec()); | |
| 992 EXPECT_EQ("http://test/", [delegate_ openerURL].spec()); | |
| 993 EXPECT_FALSE([delegate_ initiatedByUser]); | |
| 994 }; | |
| 995 | |
| 996 // Tests page title changes. | 918 // Tests page title changes. |
| 997 typedef web::WebTestWithWebState CRWWebControllerTitleTest; | 919 typedef web::WebTestWithWebState CRWWebControllerTitleTest; |
| 998 TEST_F(CRWWebControllerTitleTest, TitleChange) { | 920 TEST_F(CRWWebControllerTitleTest, TitleChange) { |
| 999 // Observes and waits for TitleWasSet call. | 921 // Observes and waits for TitleWasSet call. |
| 1000 class TitleObserver : public web::WebStateObserver { | 922 class TitleObserver : public web::WebStateObserver { |
| 1001 public: | 923 public: |
| 1002 explicit TitleObserver(web::WebState* web_state) | 924 explicit TitleObserver(web::WebState* web_state) |
| 1003 : web::WebStateObserver(web_state) {} | 925 : web::WebStateObserver(web_state) {} |
| 1004 // Returns number of times |TitleWasSet| was called. | 926 // Returns number of times |TitleWasSet| was called. |
| 1005 int title_change_count() { return title_change_count_; } | 927 int title_change_count() { return title_change_count_; } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1067 }; | 989 }; |
| 1068 | 990 |
| 1069 RenderProcessGoneObserver observer(web_state()); | 991 RenderProcessGoneObserver observer(web_state()); |
| 1070 web::SimulateWKWebViewCrash(webView_); | 992 web::SimulateWKWebViewCrash(webView_); |
| 1071 observer.WaitForRenderProcessGone(); | 993 observer.WaitForRenderProcessGone(); |
| 1072 | 994 |
| 1073 EXPECT_FALSE([web_controller() isViewAlive]); | 995 EXPECT_FALSE([web_controller() isViewAlive]); |
| 1074 }; | 996 }; |
| 1075 | 997 |
| 1076 } // namespace | 998 } // namespace |
| OLD | NEW |