Add a few more entries to CFI blacklist.
[chromium-blink-merge.git] / content / test / test_render_frame_host.cc
blob2d081ef117683eb135e8599007a263f76e7aaa27
1 // Copyright 2013 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.
5 #include "content/test/test_render_frame_host.h"
7 #include "base/command_line.h"
8 #include "content/browser/frame_host/frame_tree.h"
9 #include "content/browser/frame_host/navigation_handle_impl.h"
10 #include "content/browser/frame_host/navigation_request.h"
11 #include "content/browser/frame_host/navigator.h"
12 #include "content/browser/frame_host/navigator_impl.h"
13 #include "content/browser/frame_host/render_frame_host_delegate.h"
14 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/common/frame_messages.h"
16 #include "content/public/browser/stream_handle.h"
17 #include "content/public/common/content_switches.h"
18 #include "content/public/common/url_constants.h"
19 #include "content/test/browser_side_navigation_test_utils.h"
20 #include "content/test/test_navigation_url_loader.h"
21 #include "content/test/test_render_view_host.h"
22 #include "net/base/load_flags.h"
23 #include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
24 #include "third_party/WebKit/public/web/WebSandboxFlags.h"
25 #include "third_party/WebKit/public/web/WebTreeScopeType.h"
26 #include "ui/base/page_transition_types.h"
28 namespace content {
30 TestRenderFrameHostCreationObserver::TestRenderFrameHostCreationObserver(
31 WebContents* web_contents)
32 : WebContentsObserver(web_contents), last_created_frame_(NULL) {
35 TestRenderFrameHostCreationObserver::~TestRenderFrameHostCreationObserver() {
38 void TestRenderFrameHostCreationObserver::RenderFrameCreated(
39 RenderFrameHost* render_frame_host) {
40 last_created_frame_ = render_frame_host;
43 TestRenderFrameHost::TestRenderFrameHost(SiteInstance* site_instance,
44 RenderViewHostImpl* render_view_host,
45 RenderFrameHostDelegate* delegate,
46 RenderWidgetHostDelegate* rwh_delegate,
47 FrameTree* frame_tree,
48 FrameTreeNode* frame_tree_node,
49 int routing_id,
50 int flags)
51 : RenderFrameHostImpl(site_instance,
52 render_view_host,
53 delegate,
54 rwh_delegate,
55 frame_tree,
56 frame_tree_node,
57 routing_id,
58 flags),
59 child_creation_observer_(delegate ? delegate->GetAsWebContents() : NULL),
60 contents_mime_type_("text/html"),
61 simulate_history_list_was_cleared_(false) {
64 TestRenderFrameHost::~TestRenderFrameHost() {
67 TestRenderViewHost* TestRenderFrameHost::GetRenderViewHost() {
68 return static_cast<TestRenderViewHost*>(
69 RenderFrameHostImpl::GetRenderViewHost());
72 MockRenderProcessHost* TestRenderFrameHost::GetProcess() {
73 return static_cast<MockRenderProcessHost*>(RenderFrameHostImpl::GetProcess());
76 void TestRenderFrameHost::InitializeRenderFrameIfNeeded() {
77 if (!render_view_host()->IsRenderViewLive()) {
78 RenderViewHostTester::For(render_view_host())->CreateTestRenderView(
79 base::string16(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, -1, false);
83 TestRenderFrameHost* TestRenderFrameHost::AppendChild(
84 const std::string& frame_name) {
85 OnCreateChildFrame(GetProcess()->GetNextRoutingID(),
86 blink::WebTreeScopeType::Document, frame_name,
87 blink::WebSandboxFlags::None);
88 return static_cast<TestRenderFrameHost*>(
89 child_creation_observer_.last_created_frame());
92 void TestRenderFrameHost::SimulateNavigationStart(const GURL& url) {
93 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
94 switches::kEnableBrowserSideNavigation)) {
95 SendRendererInitiatedNavigationRequest(url, false);
96 return;
99 OnDidStartLoading(true);
100 OnDidStartProvisionalLoadForFrame(url);
103 void TestRenderFrameHost::SimulateRedirect(const GURL& new_url) {
104 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
105 switches::kEnableBrowserSideNavigation)) {
106 NavigationRequest* request = frame_tree_node_->navigation_request();
107 TestNavigationURLLoader* url_loader =
108 static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
109 CHECK(url_loader);
110 url_loader->SimulateServerRedirect(new_url);
111 return;
114 // Note that this does not simulate
115 // WebContentsImpl::DidGetRedirectForResourceRequest due to the difficulty in
116 // creating fake ResourceRequestDetails on the UI thread.
117 navigation_handle()->DidRedirectNavigation(new_url);
120 void TestRenderFrameHost::SimulateNavigationCommit(const GURL& url) {
121 if (frame_tree_node()->navigation_request())
122 PrepareForCommit();
124 FrameHostMsg_DidCommitProvisionalLoad_Params params;
125 params.page_id = ComputeNextPageID();
126 params.nav_entry_id = 0;
127 params.url = url;
128 params.transition = GetParent() ? ui::PAGE_TRANSITION_MANUAL_SUBFRAME
129 : ui::PAGE_TRANSITION_LINK;
130 params.should_update_history = true;
131 params.did_create_new_entry = true;
132 params.gesture = NavigationGestureUser;
133 params.contents_mime_type = contents_mime_type_;
134 params.is_post = false;
135 params.http_status_code = 200;
136 params.socket_address.set_host("2001:db8::1");
137 params.socket_address.set_port(80);
138 params.history_list_was_cleared = simulate_history_list_was_cleared_;
139 params.original_request_url = url;
141 url::Replacements<char> replacements;
142 replacements.ClearRef();
143 params.was_within_same_page =
144 url.ReplaceComponents(replacements) ==
145 GetLastCommittedURL().ReplaceComponents(replacements);
147 params.page_state = PageState::CreateForTesting(url, false, nullptr, nullptr);
149 SendNavigateWithParams(&params);
152 void TestRenderFrameHost::SimulateNavigationError(const GURL& url,
153 int error_code) {
154 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
155 switches::kEnableBrowserSideNavigation)) {
156 NavigationRequest* request = frame_tree_node_->navigation_request();
157 TestNavigationURLLoader* url_loader =
158 static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
159 CHECK(url_loader);
160 url_loader->SimulateError(error_code);
161 return;
164 FrameHostMsg_DidFailProvisionalLoadWithError_Params error_params;
165 error_params.error_code = error_code;
166 error_params.url = url;
167 OnDidFailProvisionalLoadWithError(error_params);
170 void TestRenderFrameHost::SimulateNavigationErrorPageCommit() {
171 CHECK(navigation_handle());
172 GURL error_url = GURL(kUnreachableWebDataURL);
173 OnDidStartProvisionalLoadForFrame(error_url);
174 FrameHostMsg_DidCommitProvisionalLoad_Params params;
175 params.page_id = ComputeNextPageID();
176 params.nav_entry_id = 0;
177 params.did_create_new_entry = true;
178 params.url = navigation_handle()->GetURL();
179 params.transition = GetParent() ? ui::PAGE_TRANSITION_MANUAL_SUBFRAME
180 : ui::PAGE_TRANSITION_LINK;
181 params.was_within_same_page = false;
182 params.url_is_unreachable = true;
183 params.page_state = PageState::CreateForTesting(navigation_handle()->GetURL(),
184 false, nullptr, nullptr);
185 SendNavigateWithParams(&params);
188 void TestRenderFrameHost::SimulateNavigationStop() {
189 if (is_loading()) {
190 OnDidStopLoading();
191 } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
192 switches::kEnableBrowserSideNavigation)) {
193 // Even if the RenderFrameHost is not loading, there may still be an
194 // ongoing navigation in the FrameTreeNode. Cancel this one as well.
195 frame_tree_node()->ResetNavigationRequest(false);
199 void TestRenderFrameHost::SetContentsMimeType(const std::string& mime_type) {
200 contents_mime_type_ = mime_type;
203 void TestRenderFrameHost::SendBeforeUnloadACK(bool proceed) {
204 base::TimeTicks now = base::TimeTicks::Now();
205 OnBeforeUnloadACK(proceed, now, now);
208 void TestRenderFrameHost::SimulateSwapOutACK() {
209 OnSwappedOut();
212 void TestRenderFrameHost::SendNavigate(int page_id,
213 int nav_entry_id,
214 bool did_create_new_entry,
215 const GURL& url) {
216 SendNavigateWithParameters(page_id, nav_entry_id, did_create_new_entry, url,
217 ui::PAGE_TRANSITION_LINK, 200,
218 ModificationCallback());
221 void TestRenderFrameHost::SendFailedNavigate(int page_id,
222 int nav_entry_id,
223 bool did_create_new_entry,
224 const GURL& url) {
225 SendNavigateWithParameters(page_id, nav_entry_id, did_create_new_entry, url,
226 ui::PAGE_TRANSITION_RELOAD, 500,
227 ModificationCallback());
230 void TestRenderFrameHost::SendNavigateWithTransition(
231 int page_id,
232 int nav_entry_id,
233 bool did_create_new_entry,
234 const GURL& url,
235 ui::PageTransition transition) {
236 SendNavigateWithParameters(page_id, nav_entry_id, did_create_new_entry, url,
237 transition, 200, ModificationCallback());
240 void TestRenderFrameHost::SendNavigateWithModificationCallback(
241 int page_id,
242 int nav_entry_id,
243 bool did_create_new_entry,
244 const GURL& url,
245 const ModificationCallback& callback) {
246 SendNavigateWithParameters(page_id, nav_entry_id, did_create_new_entry, url,
247 ui::PAGE_TRANSITION_LINK, 200, callback);
250 void TestRenderFrameHost::SendNavigateWithParameters(
251 int page_id,
252 int nav_entry_id,
253 bool did_create_new_entry,
254 const GURL& url,
255 ui::PageTransition transition,
256 int response_code,
257 const ModificationCallback& callback) {
258 // DidStartProvisionalLoad may delete the pending entry that holds |url|,
259 // so we keep a copy of it to use below.
260 GURL url_copy(url);
261 OnDidStartLoading(true);
262 OnDidStartProvisionalLoadForFrame(url_copy);
264 FrameHostMsg_DidCommitProvisionalLoad_Params params;
265 params.page_id = page_id;
266 params.nav_entry_id = nav_entry_id;
267 params.url = url_copy;
268 params.transition = transition;
269 params.should_update_history = true;
270 params.did_create_new_entry = did_create_new_entry;
271 params.gesture = NavigationGestureUser;
272 params.contents_mime_type = contents_mime_type_;
273 params.is_post = false;
274 params.http_status_code = response_code;
275 params.socket_address.set_host("2001:db8::1");
276 params.socket_address.set_port(80);
277 params.history_list_was_cleared = simulate_history_list_was_cleared_;
278 params.original_request_url = url_copy;
280 url::Replacements<char> replacements;
281 replacements.ClearRef();
282 params.was_within_same_page =
283 transition != ui::PAGE_TRANSITION_RELOAD &&
284 transition != ui::PAGE_TRANSITION_TYPED &&
285 url_copy.ReplaceComponents(replacements) ==
286 GetLastCommittedURL().ReplaceComponents(replacements);
288 params.page_state =
289 PageState::CreateForTesting(url_copy, false, nullptr, nullptr);
291 if (!callback.is_null())
292 callback.Run(&params);
294 SendNavigateWithParams(&params);
297 void TestRenderFrameHost::SendNavigateWithParams(
298 FrameHostMsg_DidCommitProvisionalLoad_Params* params) {
299 FrameHostMsg_DidCommitProvisionalLoad msg(GetRoutingID(), *params);
300 OnDidCommitProvisionalLoad(msg);
303 void TestRenderFrameHost::NavigateAndCommitRendererInitiated(
304 int page_id,
305 bool did_create_new_entry,
306 const GURL& url) {
307 SendRendererInitiatedNavigationRequest(url, false);
308 // PlzNavigate: If no network request is needed by the navigation, then there
309 // will be no NavigationRequest, nor is it necessary to simulate the network
310 // stack commit.
311 if (frame_tree_node()->navigation_request())
312 PrepareForCommit();
313 bool browser_side_navigation =
314 base::CommandLine::ForCurrentProcess()->HasSwitch(
315 switches::kEnableBrowserSideNavigation);
316 CHECK_IMPLIES(browser_side_navigation, is_loading());
317 CHECK_IMPLIES(browser_side_navigation,
318 !frame_tree_node()->navigation_request());
319 SendNavigate(page_id, 0, did_create_new_entry, url);
322 void TestRenderFrameHost::SendRendererInitiatedNavigationRequest(
323 const GURL& url,
324 bool has_user_gesture) {
325 // Since this is renderer-initiated navigation, the RenderFrame must be
326 // initialized. Do it if it hasn't happened yet.
327 InitializeRenderFrameIfNeeded();
329 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
330 switches::kEnableBrowserSideNavigation)) {
331 BeginNavigationParams begin_params("GET", std::string(), net::LOAD_NORMAL,
332 has_user_gesture);
333 CommonNavigationParams common_params;
334 common_params.url = url;
335 common_params.referrer = Referrer(GURL(), blink::WebReferrerPolicyDefault);
336 common_params.transition = ui::PAGE_TRANSITION_LINK;
337 OnBeginNavigation(common_params, begin_params,
338 scoped_refptr<ResourceRequestBody>());
342 void TestRenderFrameHost::DidDisownOpener() {
343 OnDidDisownOpener();
346 void TestRenderFrameHost::PrepareForCommit() {
347 PrepareForCommitWithServerRedirect(GURL());
350 void TestRenderFrameHost::PrepareForCommitWithServerRedirect(
351 const GURL& redirect_url) {
352 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
353 switches::kEnableBrowserSideNavigation)) {
354 // Non PlzNavigate
355 if (is_waiting_for_beforeunload_ack())
356 SendBeforeUnloadACK(true);
357 return;
360 // PlzNavigate
361 NavigationRequest* request = frame_tree_node_->navigation_request();
362 CHECK(request);
364 // Simulate a beforeUnload ACK from the renderer if the browser is waiting for
365 // it. If it runs it will update the request state.
366 if (request->state() == NavigationRequest::WAITING_FOR_RENDERER_RESPONSE)
367 SendBeforeUnloadACK(true);
369 CHECK(request->state() == NavigationRequest::STARTED);
371 TestNavigationURLLoader* url_loader =
372 static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
373 CHECK(url_loader);
375 // If a non-empty |redirect_url| was provided, simulate a server redirect.
376 if (!redirect_url.is_empty())
377 url_loader->SimulateServerRedirect(redirect_url);
379 // Simulate the network stack commit.
380 scoped_refptr<ResourceResponse> response(new ResourceResponse);
381 // TODO(carlosk): ideally with PlzNavigate it should be possible someday to
382 // fully commit the navigation at this call to CallOnResponseStarted.
383 url_loader->CallOnResponseStarted(response, MakeEmptyStream());
386 int32 TestRenderFrameHost::ComputeNextPageID() {
387 const NavigationEntryImpl* entry = static_cast<NavigationEntryImpl*>(
388 frame_tree_node()->navigator()->GetController()->GetPendingEntry());
389 DCHECK_IMPLIES(entry && entry->site_instance(),
390 entry->site_instance() == GetSiteInstance());
391 // Entry can be null when committing an error page (the pending entry was
392 // cleared during DidFailProvisionalLoad).
393 int page_id = entry ? entry->GetPageID() : -1;
394 if (page_id == -1) {
395 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(delegate());
396 page_id = web_contents->GetMaxPageIDForSiteInstance(GetSiteInstance()) + 1;
398 return page_id;
401 } // namespace content