| 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 |
| 76 void WebTestWithWebState::LoadHtml(NSString* html) { | 106 void WebTestWithWebState::LoadHtml(NSString* html) { |
| 77 LoadHtml([html UTF8String]); | 107 GURL url("https://chromium.test/"); |
| 108 LoadHtml(html, url); |
| 78 } | 109 } |
| 79 | 110 |
| 80 void WebTestWithWebState::LoadHtml(const std::string& html) { | 111 void WebTestWithWebState::LoadHtml(const std::string& html) { |
| 81 NSString* load_check = CreateLoadCheck(); | 112 LoadHtml(base::SysUTF8ToNSString(html)); |
| 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]; | |
| 118 } | 113 } |
| 119 | 114 |
| 120 void WebTestWithWebState::WaitForBackgroundTasks() { | 115 void WebTestWithWebState::WaitForBackgroundTasks() { |
| 121 // Because tasks can add new tasks to either queue, the loop continues until | 116 // Because tasks can add new tasks to either queue, the loop continues until |
| 122 // the first pass where no activity is seen from either queue. | 117 // the first pass where no activity is seen from either queue. |
| 123 bool activitySeen = false; | 118 bool activitySeen = false; |
| 124 base::MessageLoop* messageLoop = base::MessageLoop::current(); | 119 base::MessageLoop* messageLoop = base::MessageLoop::current(); |
| 125 messageLoop->AddTaskObserver(this); | 120 messageLoop->AddTaskObserver(this); |
| 126 do { | 121 do { |
| 127 activitySeen = false; | 122 activitySeen = false; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 } | 165 } |
| 171 | 166 |
| 172 web::WebState* WebTestWithWebState::web_state() { | 167 web::WebState* WebTestWithWebState::web_state() { |
| 173 return web_state_.get(); | 168 return web_state_.get(); |
| 174 } | 169 } |
| 175 | 170 |
| 176 const web::WebState* WebTestWithWebState::web_state() const { | 171 const web::WebState* WebTestWithWebState::web_state() const { |
| 177 return web_state_.get(); | 172 return web_state_.get(); |
| 178 } | 173 } |
| 179 | 174 |
| 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 | |
| 192 NSString* WebTestWithWebState::CreateLoadCheck() { | 175 NSString* WebTestWithWebState::CreateLoadCheck() { |
| 193 return [NSString stringWithFormat:@"<p style=\"display: none;\">%d</p>", | 176 return [NSString stringWithFormat:@"<p style=\"display: none;\">%d</p>", |
| 194 s_html_load_count++]; | 177 s_html_load_count++]; |
| 195 } | 178 } |
| 196 | 179 |
| 197 } // namespace web | 180 } // namespace web |
| OLD | NEW |