OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/public/test/web_test_with_web_state.h" | 5 #import "ios/web/public/test/web_test_with_web_state.h" |
6 | 6 |
7 #import <WebKit/WebKit.h> | 7 #import <WebKit/WebKit.h> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 void WebTestWithWebState::WillProcessTask( | 66 void WebTestWithWebState::WillProcessTask( |
67 const base::PendingTask& pending_task) { | 67 const base::PendingTask& pending_task) { |
68 // Nothing to do. | 68 // Nothing to do. |
69 } | 69 } |
70 | 70 |
71 void WebTestWithWebState::DidProcessTask( | 71 void WebTestWithWebState::DidProcessTask( |
72 const base::PendingTask& pending_task) { | 72 const base::PendingTask& pending_task) { |
73 processed_a_task_ = true; | 73 processed_a_task_ = true; |
74 } | 74 } |
75 | 75 |
76 void WebTestWithWebState::LoadHtml(NSString* html, const GURL& url) { | |
77 ASSERT_FALSE(web_state()->IsLoading()); | |
78 | |
79 CRWWebController* web_controller = GetWebController(web_state()); | |
80 [web_controller loadHTML:html forURL:url]; | |
81 | |
82 // Wait until the navigation is committed to update MIME type. | |
83 ASSERT_EQ(LOAD_REQUESTED, web_controller.loadPhase); | |
84 base::TimeDelta spin_delay = base::TimeDelta::FromMilliseconds(10); | |
85 while (web_controller.loadPhase != PAGE_LOADING) | |
86 base::test::ios::SpinRunLoopWithMaxDelay(spin_delay); | |
87 | |
88 // loadHTML:forURL: does not notify web view delegate about received response, | |
89 // so web controller does not get a chance to properly update MIME type and it | |
90 // should be set manually after navigation is committed but before WebState | |
91 // signal load completion and clients will start checking if MIME type is in | |
92 // fact HTML. | |
93 [web_controller webStateImpl]->SetContentsMimeType("text/html"); | |
94 | |
95 // Wait until the page is loaded. | |
96 ASSERT_EQ(PAGE_LOADING, web_controller.loadPhase); | |
97 while (web_controller.loadPhase != PAGE_LOADED) | |
98 base::test::ios::SpinRunLoopWithMaxDelay(spin_delay); | |
99 | |
100 // Wait until scripts execution becomes possible. | |
101 base::test::ios::WaitUntilCondition(^bool { | |
102 return [ExecuteJavaScript(@"0;") isEqual:@0]; | |
103 }); | |
104 } | |
105 | |
106 void WebTestWithWebState::LoadHtml(NSString* html) { | 76 void WebTestWithWebState::LoadHtml(NSString* html) { |
107 GURL url("https://chromium.test/"); | 77 LoadHtml([html UTF8String]); |
108 LoadHtml(html, url); | |
109 } | 78 } |
110 | 79 |
111 void WebTestWithWebState::LoadHtml(const std::string& html) { | 80 void WebTestWithWebState::LoadHtml(const std::string& html) { |
112 LoadHtml(base::SysUTF8ToNSString(html)); | 81 NSString* load_check = CreateLoadCheck(); |
| 82 std::string marked_html = html + [load_check UTF8String]; |
| 83 std::string encoded_html; |
| 84 base::Base64Encode(marked_html, &encoded_html); |
| 85 GURL url("data:text/html;charset=utf8;base64," + encoded_html); |
| 86 LoadURL(url); |
| 87 |
| 88 if (ResetPageIfNavigationStalled(load_check)) { |
| 89 LoadHtml(html); |
| 90 } |
| 91 } |
| 92 |
| 93 void WebTestWithWebState::LoadURL(const GURL& url) { |
| 94 // First step is to ensure that the web controller has finished any previous |
| 95 // page loads so the new load is not confused. |
| 96 while ([GetWebController(web_state()) loadPhase] != PAGE_LOADED) |
| 97 WaitForBackgroundTasks(); |
| 98 id originalMockDelegate = |
| 99 [OCMockObject niceMockForProtocol:@protocol(CRWWebDelegate)]; |
| 100 id mockDelegate = |
| 101 [[WebDelegateMock alloc] initWithRepresentedObject:originalMockDelegate]; |
| 102 id existingDelegate = GetWebController(web_state()).delegate; |
| 103 GetWebController(web_state()).delegate = mockDelegate; |
| 104 |
| 105 web::NavigationManagerImpl& navManager = |
| 106 [GetWebController(web_state()) webStateImpl]->GetNavigationManagerImpl(); |
| 107 navManager.InitializeSession(@"name", nil, NO, 0); |
| 108 [navManager.GetSessionController() addPendingEntry:url |
| 109 referrer:web::Referrer() |
| 110 transition:ui::PAGE_TRANSITION_TYPED |
| 111 rendererInitiated:NO]; |
| 112 |
| 113 [GetWebController(web_state()) loadCurrentURL]; |
| 114 while ([GetWebController(web_state()) loadPhase] != PAGE_LOADED) |
| 115 WaitForBackgroundTasks(); |
| 116 GetWebController(web_state()).delegate = existingDelegate; |
| 117 [web_state()->GetView() layoutIfNeeded]; |
113 } | 118 } |
114 | 119 |
115 void WebTestWithWebState::WaitForBackgroundTasks() { | 120 void WebTestWithWebState::WaitForBackgroundTasks() { |
116 // Because tasks can add new tasks to either queue, the loop continues until | 121 // Because tasks can add new tasks to either queue, the loop continues until |
117 // the first pass where no activity is seen from either queue. | 122 // the first pass where no activity is seen from either queue. |
118 bool activitySeen = false; | 123 bool activitySeen = false; |
119 base::MessageLoop* messageLoop = base::MessageLoop::current(); | 124 base::MessageLoop* messageLoop = base::MessageLoop::current(); |
120 messageLoop->AddTaskObserver(this); | 125 messageLoop->AddTaskObserver(this); |
121 do { | 126 do { |
122 activitySeen = false; | 127 activitySeen = false; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 } | 170 } |
166 | 171 |
167 web::WebState* WebTestWithWebState::web_state() { | 172 web::WebState* WebTestWithWebState::web_state() { |
168 return web_state_.get(); | 173 return web_state_.get(); |
169 } | 174 } |
170 | 175 |
171 const web::WebState* WebTestWithWebState::web_state() const { | 176 const web::WebState* WebTestWithWebState::web_state() const { |
172 return web_state_.get(); | 177 return web_state_.get(); |
173 } | 178 } |
174 | 179 |
| 180 bool WebTestWithWebState::ResetPageIfNavigationStalled(NSString* load_check) { |
| 181 id inner_html = ExecuteJavaScript( |
| 182 @"(document && document.body && document.body.innerHTML) || 'undefined'"); |
| 183 if (![inner_html rangeOfString:load_check].length) { |
| 184 web_state_->SetWebUsageEnabled(false); |
| 185 web_state_->SetWebUsageEnabled(true); |
| 186 [GetWebController(web_state()) triggerPendingLoad]; |
| 187 return true; |
| 188 } |
| 189 return false; |
| 190 } |
| 191 |
175 NSString* WebTestWithWebState::CreateLoadCheck() { | 192 NSString* WebTestWithWebState::CreateLoadCheck() { |
176 return [NSString stringWithFormat:@"<p style=\"display: none;\">%d</p>", | 193 return [NSString stringWithFormat:@"<p style=\"display: none;\">%d</p>", |
177 s_html_load_count++]; | 194 s_html_load_count++]; |
178 } | 195 } |
179 | 196 |
180 } // namespace web | 197 } // namespace web |
OLD | NEW |