| 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 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 [web_controller() webStateImpl]->OnPageLoaded(GURL("http://test"), false); | 818 [web_controller() webStateImpl]->OnPageLoaded(GURL("http://test"), false); |
| 857 EXPECT_EQ(0, [observer pageLoadedCount]); | 819 EXPECT_EQ(0, [observer pageLoadedCount]); |
| 858 [web_controller() webStateImpl]->OnPageLoaded(GURL("http://test"), true); | 820 [web_controller() webStateImpl]->OnPageLoaded(GURL("http://test"), true); |
| 859 EXPECT_EQ(1, [observer pageLoadedCount]); | 821 EXPECT_EQ(1, [observer pageLoadedCount]); |
| 860 | 822 |
| 861 [web_controller() removeObserver:observer]; | 823 [web_controller() removeObserver:observer]; |
| 862 EXPECT_EQ(0u, [web_controller() observerCount]); | 824 EXPECT_EQ(0u, [web_controller() observerCount]); |
| 863 }; | 825 }; |
| 864 | 826 |
| 865 // Test fixture for window.open tests. | 827 // Test fixture for window.open tests. |
| 866 class CRWWebControllerWindowOpenTest : public web::WebTestWithWebController { | 828 class WindowOpenByDomTest : public web::WebTestWithWebController { |
| 867 protected: | 829 protected: |
| 830 WindowOpenByDomTest() : opener_url_("http://test") {} |
| 831 |
| 868 void SetUp() override { | 832 void SetUp() override { |
| 869 web::WebTestWithWebController::SetUp(); | 833 WebTestWithWebController::SetUp(); |
| 870 | 834 web_state()->SetDelegate(&delegate_); |
| 871 // Configure web delegate. | 835 LoadHtml(@"<html><body></body></html>", opener_url_); |
| 872 delegate_.reset([[MockInteractionLoader alloc] | |
| 873 initWithRepresentedObject: | |
| 874 [OCMockObject niceMockForProtocol:@protocol(CRWWebDelegate)]]); | |
| 875 ASSERT_TRUE([delegate_ blockPopups]); | |
| 876 [web_controller() setDelegate:delegate_]; | |
| 877 | |
| 878 // Configure child web state. | |
| 879 child_web_state_.reset(new web::WebStateImpl(GetBrowserState())); | |
| 880 child_web_state_->SetWebUsageEnabled(true); | |
| 881 [delegate_ setChildWebController:child_web_state_->GetWebController()]; | |
| 882 | |
| 883 // Configure child web controller's session controller mock. | |
| 884 id sessionController = | |
| 885 [OCMockObject niceMockForClass:[CRWSessionController class]]; | |
| 886 BOOL yes = YES; | |
| 887 [[[sessionController stub] andReturnValue:OCMOCK_VALUE(yes)] isOpenedByDOM]; | |
| 888 child_web_state_->GetNavigationManagerImpl().SetSessionController( | |
| 889 sessionController); | |
| 890 | |
| 891 LoadHtml(@"<html><body></body></html>", GURL("http://test")); | |
| 892 } | |
| 893 void TearDown() override { | |
| 894 EXPECT_OCMOCK_VERIFY(delegate_); | |
| 895 [web_controller() setDelegate:nil]; | |
| 896 | |
| 897 web::WebTestWithWebController::TearDown(); | |
| 898 } | 836 } |
| 899 // Executes JavaScript that opens a new window and returns evaluation result | 837 // Executes JavaScript that opens a new window and returns evaluation result |
| 900 // as a string. | 838 // as a string. |
| 901 id OpenWindowByDOM() { | 839 id OpenWindowByDom() { |
| 902 NSString* const kOpenWindowScript = | 840 NSString* const kOpenWindowScript = |
| 903 @"var w = window.open('javascript:void(0);', target='_blank');" | 841 @"var w = window.open('javascript:void(0);', target='_blank');" |
| 904 "w ? w.toString() : null;"; | 842 "w ? w.toString() : null;"; |
| 905 id windowJSObject = ExecuteJavaScript(kOpenWindowScript); | 843 id windowJSObject = ExecuteJavaScript(kOpenWindowScript); |
| 906 WaitForBackgroundTasks(); | 844 WaitForBackgroundTasks(); |
| 907 return windowJSObject; | 845 return windowJSObject; |
| 908 } | 846 } |
| 909 // A CRWWebDelegate mock used for testing. | 847 // URL of a page which opens child windows. |
| 910 base::scoped_nsobject<id> delegate_; | 848 const GURL opener_url_; |
| 911 // A child WebState used for testing. | 849 web::TestWebStateDelegate delegate_; |
| 912 std::unique_ptr<web::WebStateImpl> child_web_state_; | |
| 913 }; | 850 }; |
| 914 | 851 |
| 915 // Tests that absence of web delegate is handled gracefully. | 852 // Tests that absence of web state delegate is handled gracefully. |
| 916 TEST_F(CRWWebControllerWindowOpenTest, NoDelegate) { | 853 TEST_F(WindowOpenByDomTest, NoDelegate) { |
| 917 [web_controller() setDelegate:nil]; | 854 web_state()->SetDelegate(nullptr); |
| 918 | 855 |
| 919 EXPECT_NSEQ([NSNull null], OpenWindowByDOM()); | 856 EXPECT_NSEQ([NSNull null], OpenWindowByDom()); |
| 920 | 857 |
| 921 EXPECT_FALSE([delegate_ webController]); | 858 EXPECT_TRUE(delegate_.child_windows().empty()); |
| 922 EXPECT_FALSE([delegate_ childURL].is_valid()); | 859 EXPECT_TRUE(delegate_.popups().empty()); |
| 923 EXPECT_FALSE([delegate_ openerURL].is_valid()); | |
| 924 EXPECT_FALSE([delegate_ initiatedByUser]); | |
| 925 } | 860 } |
| 926 | 861 |
| 927 // Tests that window.open triggered by user gesture opens a new non-popup | 862 // Tests that window.open triggered by user gesture opens a new non-popup |
| 928 // window. | 863 // window. |
| 929 TEST_F(CRWWebControllerWindowOpenTest, OpenWithUserGesture) { | 864 TEST_F(WindowOpenByDomTest, OpenWithUserGesture) { |
| 930 [web_controller() touched:YES]; | 865 [web_controller() touched:YES]; |
| 931 EXPECT_NSEQ(@"[object Window]", OpenWindowByDOM()); | 866 EXPECT_NSEQ(@"[object Window]", OpenWindowByDom()); |
| 932 | 867 |
| 933 EXPECT_EQ(web_controller(), [delegate_ webController]); | 868 ASSERT_EQ(1U, delegate_.child_windows().size()); |
| 934 EXPECT_EQ("javascript:void(0);", [delegate_ childURL].spec()); | 869 ASSERT_TRUE(delegate_.child_windows()[0]); |
| 935 EXPECT_EQ("http://test/", [delegate_ openerURL].spec()); | 870 EXPECT_TRUE(delegate_.popups().empty()); |
| 936 EXPECT_TRUE([delegate_ initiatedByUser]); | |
| 937 } | 871 } |
| 938 | 872 |
| 939 // Tests that window.open executed w/o user gesture does not open a new window. | 873 // Tests that window.open executed w/o user gesture does not open a new window, |
| 940 // Once the blocked popup is allowed a new window is opened. | 874 // but blocks popup instead. |
| 941 TEST_F(CRWWebControllerWindowOpenTest, AllowPopup) { | 875 TEST_F(WindowOpenByDomTest, BlockPopup) { |
| 942 ASSERT_FALSE([web_controller() userIsInteracting]); | 876 ASSERT_FALSE([web_controller() userIsInteracting]); |
| 943 EXPECT_NSEQ([NSNull null], OpenWindowByDOM()); | 877 EXPECT_NSEQ([NSNull null], OpenWindowByDom()); |
| 944 | 878 |
| 945 EXPECT_EQ(web_controller(), [delegate_ webController]); | 879 EXPECT_TRUE(delegate_.child_windows().empty()); |
| 946 EXPECT_EQ("javascript:void(0);", [delegate_ childURL].spec()); | 880 ASSERT_EQ(1U, delegate_.popups().size()); |
| 947 EXPECT_EQ("http://test/", [delegate_ openerURL].spec()); | 881 EXPECT_EQ(GURL("javascript:void(0);"), delegate_.popups()[0].url); |
| 948 EXPECT_FALSE([delegate_ initiatedByUser]); | 882 EXPECT_EQ(opener_url_, delegate_.popups()[0].opener_url); |
| 949 } | 883 } |
| 950 | 884 |
| 951 // Tests that window.open executed w/o user gesture opens a new window, assuming | 885 // Tests that window.open executed w/o user gesture opens a new window, assuming |
| 952 // that delegate allows popups. | 886 // that delegate allows popups. |
| 953 TEST_F(CRWWebControllerWindowOpenTest, DontBlockPopup) { | 887 TEST_F(WindowOpenByDomTest, DontBlockPopup) { |
| 954 [delegate_ setBlockPopups:NO]; | 888 delegate_.allow_popups(opener_url_); |
| 955 EXPECT_NSEQ(@"[object Window]", OpenWindowByDOM()); | 889 EXPECT_NSEQ(@"[object Window]", OpenWindowByDom()); |
| 956 | 890 |
| 957 EXPECT_EQ(web_controller(), [delegate_ webController]); | 891 ASSERT_EQ(1U, delegate_.child_windows().size()); |
| 958 EXPECT_EQ("javascript:void(0);", [delegate_ childURL].spec()); | 892 ASSERT_TRUE(delegate_.child_windows()[0]); |
| 959 EXPECT_EQ("http://test/", [delegate_ openerURL].spec()); | 893 EXPECT_TRUE(delegate_.popups().empty()); |
| 960 EXPECT_FALSE([delegate_ initiatedByUser]); | |
| 961 } | 894 } |
| 962 | 895 |
| 963 // Tests that window.open executed w/o user gesture does not open a new window. | |
| 964 TEST_F(CRWWebControllerWindowOpenTest, BlockPopup) { | |
| 965 ASSERT_FALSE([web_controller() userIsInteracting]); | |
| 966 EXPECT_NSEQ([NSNull null], OpenWindowByDOM()); | |
| 967 | |
| 968 EXPECT_EQ(web_controller(), [delegate_ webController]); | |
| 969 EXPECT_EQ("javascript:void(0);", [delegate_ childURL].spec()); | |
| 970 EXPECT_EQ("http://test/", [delegate_ openerURL].spec()); | |
| 971 EXPECT_FALSE([delegate_ initiatedByUser]); | |
| 972 }; | |
| 973 | |
| 974 // Tests page title changes. | 896 // Tests page title changes. |
| 975 typedef web::WebTestWithWebState CRWWebControllerTitleTest; | 897 typedef web::WebTestWithWebState CRWWebControllerTitleTest; |
| 976 TEST_F(CRWWebControllerTitleTest, TitleChange) { | 898 TEST_F(CRWWebControllerTitleTest, TitleChange) { |
| 977 // Observes and waits for TitleWasSet call. | 899 // Observes and waits for TitleWasSet call. |
| 978 class TitleObserver : public web::WebStateObserver { | 900 class TitleObserver : public web::WebStateObserver { |
| 979 public: | 901 public: |
| 980 explicit TitleObserver(web::WebState* web_state) | 902 explicit TitleObserver(web::WebState* web_state) |
| 981 : web::WebStateObserver(web_state) {} | 903 : web::WebStateObserver(web_state) {} |
| 982 // Returns number of times |TitleWasSet| was called. | 904 // Returns number of times |TitleWasSet| was called. |
| 983 int title_change_count() { return title_change_count_; } | 905 int title_change_count() { return title_change_count_; } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 web::TestWebStateObserver* observer_ptr = &observer; | 953 web::TestWebStateObserver* observer_ptr = &observer; |
| 1032 web::SimulateWKWebViewCrash(webView_); | 954 web::SimulateWKWebViewCrash(webView_); |
| 1033 base::test::ios::WaitUntilCondition(^bool() { | 955 base::test::ios::WaitUntilCondition(^bool() { |
| 1034 return observer_ptr->render_process_gone_info(); | 956 return observer_ptr->render_process_gone_info(); |
| 1035 }); | 957 }); |
| 1036 EXPECT_EQ(web_state(), observer.render_process_gone_info()->web_state); | 958 EXPECT_EQ(web_state(), observer.render_process_gone_info()->web_state); |
| 1037 EXPECT_FALSE([web_controller() isViewAlive]); | 959 EXPECT_FALSE([web_controller() isViewAlive]); |
| 1038 }; | 960 }; |
| 1039 | 961 |
| 1040 } // namespace | 962 } // namespace |
| OLD | NEW |