Skip to content

Commit

Permalink
Ensure same-document browser-initiated navigations keep base URLs.
Browse files Browse the repository at this point in the history
This CLs ensures that same-document browser-initiated navigations on
documents loaded from a data URL with a valid base URL will not modify
the document URL. It will remain the base URL instead of reverting to
the data URL.

Bug: 1082141

Change-Id: I8347b5e82829fbbb3252bd4aa6393bbc353201fd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2198837
Commit-Queue: Camille Lamy <clamy@chromium.org>
Reviewed-by: Camille Lamy <clamy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#777352}
  • Loading branch information
Hui Wang authored and Commit Bot committed Jun 11, 2020
1 parent cf8885a commit 4ac5a66
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -11112,4 +11112,72 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
}

// Checks that a browser-initiated same-document navigation on a page which has
// a valid base URL preserves the base URL.
// See https://crbug.com/1082141.
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadDataWithBaseURLSameDocumentNavigation) {
// LoadDataWithBaseURL is never subject to --site-per-process policy today
// (this API is only used by Android WebView [where OOPIFs have not shipped
// yet] and GuestView cases [which always hosts guests inside a renderer
// without an origin lock]). Therefore, skip the test in --site-per-process
// mode to avoid renderer kills which won't happen in practice as described
// above.
//
// TODO(https://crbug.com/962643): Consider enabling this test once Android
// Webview or WebView guests support OOPIFs and/or origin locks.
if (AreAllSitesIsolatedForTesting())
return;

const GURL base_url("http://baseurl");
const GURL history_url("http://history");
const std::string data = "<html><title>One</title><body>foo</body></html>";
const GURL data_url = GURL("data:text/html;charset=utf-8," + data);

NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
shell()->web_contents()->GetController());

{
TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
shell()->LoadDataWithBaseURL(history_url, data, base_url);
same_tab_observer.Wait();
}

// Verify the last committed NavigationEntry.
NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
EXPECT_EQ(base_url, entry->GetBaseURLForDataURL());
EXPECT_EQ(history_url, entry->GetVirtualURL());
EXPECT_EQ(history_url, entry->GetHistoryURLForDataURL());
EXPECT_EQ(data_url, entry->GetURL());

{
// Make a same-document navigation via history.pushState.
TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
EXPECT_TRUE(ExecuteScript(shell(), "history.pushState('', 'test', '#')"));
same_tab_observer.Wait();
}

// Verify the last committed NavigationEntry.
entry = controller.GetLastCommittedEntry();
EXPECT_EQ(base_url, entry->GetBaseURLForDataURL());
EXPECT_EQ(history_url, entry->GetVirtualURL());
EXPECT_EQ(history_url, entry->GetHistoryURLForDataURL());
EXPECT_EQ(data_url, entry->GetURL());

{
// Go back.
TestNavigationObserver back_load_observer(shell()->web_contents());
controller.GoBack();
back_load_observer.Wait();
}

// Verify the last committed NavigationEntry.
entry = controller.GetLastCommittedEntry();
EXPECT_EQ(base_url, entry->GetBaseURLForDataURL());
EXPECT_EQ(history_url, entry->GetVirtualURL());
EXPECT_EQ(history_url, entry->GetHistoryURLForDataURL());
EXPECT_EQ(data_url, entry->GetURL());
EXPECT_EQ(base_url, EvalJs(shell(), "document.URL"));
}

} // namespace content
15 changes: 14 additions & 1 deletion content/renderer/render_frame_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3469,6 +3469,20 @@ void RenderFrameImpl::CommitSameDocumentNavigation(

if (commit_status == blink::mojom::CommitResult::Ok) {
base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
// Same-document navigations on data URLs loaded with a valid base URL
// should keep the base URL as document URL.
bool use_base_url_for_data_url =
!common_params->base_url_for_data_url.is_empty();
#if defined(OS_ANDROID)
use_base_url_for_data_url |= !commit_params->data_url_as_string.empty();
#endif

GURL url;
if (is_main_frame_ && use_base_url_for_data_url) {
url = common_params->base_url_for_data_url;
} else {
url = common_params->url;
}
bool is_client_redirect =
!!(common_params->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT);
DocumentState* original_document_state =
Expand All @@ -3481,7 +3495,6 @@ void RenderFrameImpl::CommitSameDocumentNavigation(
InternalDocumentStateData::FromDocumentState(original_document_state));
// This is a browser-initiated same-document navigation (as opposed to a
// fragment link click), therefore |was_initiated_in_this_frame| is false.
auto url = common_params->url;
internal_data->set_navigation_state(NavigationState::CreateBrowserInitiated(
std::move(common_params), std::move(commit_params),
mojom::NavigationClient::CommitNavigationCallback(), nullptr,
Expand Down

0 comments on commit 4ac5a66

Please sign in to comment.