web_view_from_wk_web_view_configuration_inttest.mm 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #import <ChromeWebView/ChromeWebView.h>
  5. #import <Foundation/Foundation.h>
  6. #import "base/test/ios/wait_util.h"
  7. #import "ios/web/common/uikit_ui_util.h"
  8. #import "ios/web_view/test/observer.h"
  9. #import "ios/web_view/test/web_view_inttest_base.h"
  10. #import "ios/web_view/test/web_view_test_util.h"
  11. #import "net/base/mac/url_conversions.h"
  12. #include "net/test/embedded_test_server/embedded_test_server.h"
  13. #include "testing/gtest_mac.h"
  14. #include "url/gurl.h"
  15. #if !defined(__has_feature) || !__has_feature(objc_arc)
  16. #error "This file requires ARC support."
  17. #endif
  18. namespace ios_web_view {
  19. // Tests if a CWVWebView can be created from a WKWebViewConfiguration outside
  20. // //ios/web
  21. class WebViewFromWKWebViewConfigurationTest : public WebViewInttestBase {
  22. public:
  23. // This method is called by the delegate method called when window.open() is
  24. // called, and the |webView| argument is the newly opened CWVWebView by the
  25. // window.open() call in a normal WKWebView. Saves the |webView| for further
  26. // tests and inserts it into the View Hierarchy tree.
  27. void SetWebView(CWVWebView* webView) {
  28. [web_view_ removeFromSuperview];
  29. web_view_ = webView;
  30. UIViewController* view_controller = [GetAnyKeyWindow() rootViewController];
  31. [view_controller.view addSubview:web_view_];
  32. }
  33. // This method is called by the delegate method called when window.open() is
  34. // called, and the |returned_wk_web_view| argument is the internal WKWebView
  35. // of the newly opened CWVWebView by the window.open() call in a normal
  36. // WKWebView. Saves the |returned_wk_web_view| for further tests.
  37. void SetReturnedWKWebView(WKWebView* returned_wk_web_view) {
  38. returned_wk_web_view_ = returned_wk_web_view;
  39. }
  40. protected:
  41. WebViewFromWKWebViewConfigurationTest() {
  42. // This |CWVWebView *web_view_| is inherited from the base class, but in
  43. // this test case I don't hope to use it, because I need to test a newly
  44. // opened CWVWebView by a window.open() call in a normal WKWebView, instead
  45. // of this one directly generated by the base class from default
  46. // configuration.
  47. [web_view_ removeFromSuperview];
  48. web_view_ = nil;
  49. }
  50. void GenerateTestPageUrls() {
  51. window1_url_ = GetUrlForPageWithHtmlBody("<p>page1</p>");
  52. window2_url_ = GetUrlForPageWithHtmlBody("<p>page2</p>");
  53. }
  54. WKWebView* returned_wk_web_view_ = nil;
  55. GURL window1_url_;
  56. GURL window2_url_;
  57. };
  58. } // namespace ios_web_view
  59. @interface WKUIDelegateForTest : NSObject <WKUIDelegate>
  60. @property(nonatomic, strong) CWVWebViewConfiguration* CWVConfiguration;
  61. - (instancetype)init NS_UNAVAILABLE;
  62. - (instancetype)initWithTest:
  63. (ios_web_view::WebViewFromWKWebViewConfigurationTest*)test
  64. NS_DESIGNATED_INITIALIZER;
  65. @end
  66. @implementation WKUIDelegateForTest {
  67. ios_web_view::WebViewFromWKWebViewConfigurationTest* _test;
  68. }
  69. - (instancetype)initWithTest:
  70. (ios_web_view::WebViewFromWKWebViewConfigurationTest*)test {
  71. self = [super init];
  72. if (self) {
  73. _test = test;
  74. }
  75. return self;
  76. }
  77. - (WKWebView*)webView:(WKWebView*)webView
  78. createWebViewWithConfiguration:(WKWebViewConfiguration*)configuration
  79. forNavigationAction:(WKNavigationAction*)action
  80. windowFeatures:(WKWindowFeatures*)windowFeatures {
  81. WKWebView* created_web_view = nil;
  82. configuration.userContentController = [[WKUserContentController alloc] init];
  83. _test->SetWebView([[CWVWebView alloc] initWithFrame:UIScreen.mainScreen.bounds
  84. configuration:self.CWVConfiguration
  85. WKConfiguration:configuration
  86. createdWKWebView:&created_web_view]);
  87. _test->SetReturnedWKWebView(created_web_view);
  88. return created_web_view;
  89. }
  90. @end
  91. @interface NavigationFinishedObserver
  92. : NSObject <WKNavigationDelegate, CWVNavigationDelegate>
  93. @property(nonatomic) BOOL navigationFinished;
  94. @end
  95. @implementation NavigationFinishedObserver
  96. - (void)webView:(WKWebView*)webView
  97. didFinishNavigation:(WKNavigation*)navigation {
  98. self.navigationFinished = YES;
  99. }
  100. - (void)webViewDidFinishNavigation:(CWVWebView*)webView {
  101. self.navigationFinished = YES;
  102. }
  103. @end
  104. namespace ios_web_view {
  105. // Tests if a CWVWebView can be created from -[CWVWebView
  106. // initWithFrame:configuration:WKConfiguration:createdWKWebView]
  107. TEST_F(WebViewFromWKWebViewConfigurationTest, FromWKWebViewConfiguration) {
  108. ASSERT_TRUE(test_server_->Start());
  109. CGRect frame = UIScreen.mainScreen.bounds;
  110. WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init];
  111. WKWebView* wk_web_view = [[WKWebView alloc] initWithFrame:frame
  112. configuration:config];
  113. WKUIDelegateForTest* wk_ui_delegate_for_test =
  114. [[WKUIDelegateForTest alloc] initWithTest:this];
  115. wk_web_view.UIDelegate = wk_ui_delegate_for_test;
  116. NavigationFinishedObserver* observer =
  117. [[NavigationFinishedObserver alloc] init];
  118. UIViewController* view_controller = [GetAnyKeyWindow() rootViewController];
  119. [view_controller.view addSubview:wk_web_view];
  120. // Loads a page in wk_web_view and waits for its completion
  121. GenerateTestPageUrls();
  122. wk_web_view.navigationDelegate = observer;
  123. [wk_web_view loadRequest:[[NSURLRequest alloc]
  124. initWithURL:net::NSURLWithGURL(window1_url_)]];
  125. using base::test::ios::kWaitForPageLoadTimeout;
  126. ASSERT_TRUE(
  127. base::test::ios::WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
  128. return observer.navigationFinished;
  129. }));
  130. wk_web_view.navigationDelegate = nil;
  131. // Checks if the page in window1 (wk_web_view) is loaded, by a line of
  132. // JavaScript
  133. __block BOOL is_js_evaluated = NO;
  134. [wk_web_view evaluateJavaScript:@"document.body.innerText"
  135. completionHandler:^(NSString* result, NSError* error) {
  136. ASSERT_FALSE(error);
  137. EXPECT_NSEQ(@"page1", result);
  138. is_js_evaluated = YES;
  139. }];
  140. using base::test::ios::kWaitForJSCompletionTimeout;
  141. ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
  142. kWaitForJSCompletionTimeout, ^{
  143. return is_js_evaluated;
  144. }));
  145. // Opens multiple windows from the original wk_web_view for testing
  146. for (int i = 0; i < 10; i++) {
  147. // Tries different CWV configs.
  148. switch (i % 3) {
  149. case 0:
  150. wk_ui_delegate_for_test.CWVConfiguration =
  151. [CWVWebViewConfiguration defaultConfiguration];
  152. break;
  153. case 1:
  154. wk_ui_delegate_for_test.CWVConfiguration =
  155. [CWVWebViewConfiguration incognitoConfiguration];
  156. break;
  157. case 2:
  158. wk_ui_delegate_for_test.CWVConfiguration =
  159. [CWVWebViewConfiguration nonPersistentConfiguration];
  160. break;
  161. }
  162. // Opens a new CWVWebView from the wk_web_view
  163. NSString* url_string = net::NSURLWithGURL(window2_url_).absoluteString;
  164. NSString* script =
  165. [NSString stringWithFormat:@"window.open('%@')", url_string];
  166. is_js_evaluated = NO;
  167. [wk_web_view evaluateJavaScript:script
  168. completionHandler:^(NSString* result, NSError* error) {
  169. is_js_evaluated = YES;
  170. }];
  171. ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
  172. kWaitForJSCompletionTimeout, ^{
  173. return is_js_evaluated;
  174. }));
  175. ASSERT_TRUE(returned_wk_web_view_);
  176. ASSERT_TRUE(web_view_);
  177. // Waits for the page in window2 (CWVWebView *web_view_) to be loaded
  178. observer.navigationFinished = NO;
  179. web_view_.navigationDelegate = observer;
  180. ASSERT_TRUE(
  181. base::test::ios::WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
  182. return observer.navigationFinished;
  183. }));
  184. web_view_.navigationDelegate = nil;
  185. // Checks if the page in web_view_ is loaded successfully
  186. NSString* inner_text =
  187. test::EvaluateJavaScript(web_view_, @"document.body.innerText");
  188. EXPECT_NSEQ(@"page2", inner_text);
  189. }
  190. [wk_web_view removeFromSuperview];
  191. }
  192. } // namespace ios_web_view