summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjaphet@chromium.org <japhet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-04 09:00:39 +0000
committerjaphet@chromium.org <japhet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-04 09:00:39 +0000
commit8d5cb21f876a51c4fddcb90954e0dd819a09a7a5 (patch)
tree0005719b9fbf9fd1757f5d028f557215487d1645
parentce3651bc735d21ca677642616c454cf2e97797ca (diff)
downloadchromium_src-8d5cb21f876a51c4fddcb90954e0dd819a09a7a5.zip
chromium_src-8d5cb21f876a51c4fddcb90954e0dd819a09a7a5.tar.gz
chromium_src-8d5cb21f876a51c4fddcb90954e0dd819a09a7a5.tar.bz2
Trust the renderer's same-document navigation flag if it is a same-origin nav.
Currently in AreURLsInPageNavigation, we only trust renderer_says_in_page if the before and after urls are identical. This prevents us from correctly classifying history.pushState and history.replaceState navigations as in-page. Navigations via the history API are required to be same-origin, but can differ by more than just the ref component, so we get the correct behavior without the renderer process being able to lie about a cross-origin navigation. BUG=138324 TEST=Added cases to NavigationControllerTest.IsInPageNavigation Review URL: https://codereview.chromium.org/304763002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274734 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContentsClient.java4
-rw-r--r--chrome/browser/extensions/active_script_controller_unittest.cc6
-rw-r--r--chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc4
-rw-r--r--chrome/browser/translate/translate_manager_render_view_host_unittest.cc8
-rw-r--r--content/browser/android/web_contents_observer_android.cc17
-rw-r--r--content/browser/frame_host/navigation_controller_impl.cc2
-rw-r--r--content/browser/frame_host/navigation_controller_impl.h10
-rw-r--r--content/browser/frame_host/navigation_controller_impl_unittest.cc34
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java2
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java6
-rw-r--r--content/public/test/test_renderer_host.cc3
-rw-r--r--content/test/test_render_frame_host.cc10
12 files changed, 72 insertions, 34 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
index e5ce027..61486bb 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -89,10 +89,10 @@ public abstract class AwContentsClient {
@Override
public void didNavigateMainFrame(String url, String baseUrl,
- boolean isNavigationToDifferentPage, boolean isNavigationInPage) {
+ boolean isNavigationToDifferentPage, boolean isFragmentNavigation) {
// This is here to emulate the Classic WebView firing onPageFinished for main frame
// navigations where only the hash fragment changes.
- if (isNavigationInPage) {
+ if (isFragmentNavigation) {
AwContentsClient.this.onPageFinished(url);
}
}
diff --git a/chrome/browser/extensions/active_script_controller_unittest.cc b/chrome/browser/extensions/active_script_controller_unittest.cc
index a670a53f..0b40328 100644
--- a/chrome/browser/extensions/active_script_controller_unittest.cc
+++ b/chrome/browser/extensions/active_script_controller_unittest.cc
@@ -219,9 +219,9 @@ TEST_F(ActiveScriptControllerUnitTest, PendingInjectionsRemovedAtNavigation) {
EXPECT_TRUE(controller()->GetActionForExtension(extension));
EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));
- // Navigate away. This should remove the pending injection, and we should not
+ // Reload. This should remove the pending injection, and we should not
// execute anything.
- NavigateAndCommit(GURL("https://www.google.com"));
+ Reload();
EXPECT_FALSE(controller()->GetActionForExtension(extension));
EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));
@@ -281,7 +281,7 @@ TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsUseActiveTabPermissions) {
EXPECT_FALSE(controller()->RequiresUserConsentForScriptInjection(extension));
// Also test that granting active tab runs any pending tasks.
- NavigateAndCommit(GURL("https://www.google.com"));
+ Reload();
// Navigating should mean we need permission again.
EXPECT_TRUE(controller()->RequiresUserConsentForScriptInjection(extension));
diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc
index 4ca5415..57d8050 100644
--- a/chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc
+++ b/chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc
@@ -291,7 +291,7 @@ TEST_F(GeolocationPermissionContextTests, GeolocationEnabledDisabled) {
base::string16 text_0 = infobar_delegate_0->GetButtonLabel(
ConfirmInfoBarDelegate::BUTTON_OK);
- NavigateAndCommit(requesting_frame);
+ Reload();
MockGoogleLocationSettingsHelper::SetLocationStatus(true, false);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
@@ -303,7 +303,7 @@ TEST_F(GeolocationPermissionContextTests, GeolocationEnabledDisabled) {
ConfirmInfoBarDelegate::BUTTON_OK);
EXPECT_NE(text_0, text_1);
- NavigateAndCommit(requesting_frame);
+ Reload();
MockGoogleLocationSettingsHelper::SetLocationStatus(false, false);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame);
diff --git a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc
index 8e9d444..fadcd1b 100644
--- a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc
+++ b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc
@@ -94,7 +94,10 @@ class TranslateManagerRenderViewHostTest
void SimulateNavigation(const GURL& url,
const std::string& lang,
bool page_translatable) {
- NavigateAndCommit(url);
+ if (rvh()->GetMainFrame()->GetLastCommittedURL() == url)
+ Reload();
+ else
+ NavigateAndCommit(url);
SimulateOnTranslateLanguageDetermined(lang, page_translatable);
}
@@ -794,7 +797,8 @@ TEST_F(TranslateManagerRenderViewHostTest, ReloadFromLocationBar) {
NavEntryCommittedObserver nav_observer(web_contents());
web_contents()->GetController().LoadURL(
url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string());
- rvh_tester()->SendNavigate(0, url);
+ rvh_tester()->SendNavigateWithTransition(
+ 0, url, content::PAGE_TRANSITION_TYPED);
// Test that we are really getting a same page navigation, the test would be
// useless if it was not the case.
diff --git a/content/browser/android/web_contents_observer_android.cc b/content/browser/android/web_contents_observer_android.cc
index 72b2241..19a622a 100644
--- a/content/browser/android/web_contents_observer_android.cc
+++ b/content/browser/android/web_contents_observer_android.cc
@@ -129,12 +129,23 @@ void WebContentsObserverAndroid::DidNavigateMainFrame(
ConvertUTF8ToJavaString(env, params.url.spec()));
ScopedJavaLocalRef<jstring> jstring_base_url(
ConvertUTF8ToJavaString(env, params.base_url.spec()));
+
// See http://crbug.com/251330 for why it's determined this way.
- bool in_page_navigation =
- details.type == NAVIGATION_TYPE_IN_PAGE || details.is_in_page;
+ url::Replacements<char> replacements;
+ replacements.ClearRef();
+ bool urls_same_ignoring_fragment =
+ params.url.ReplaceComponents(replacements) ==
+ details.previous_url.ReplaceComponents(replacements);
+
+ // is_fragment_navigation is indicative of the intent of this variable.
+ // However, there isn't sufficient information here to determine whether this
+ // is actually a fragment navigation, or a history API navigation to a URL
+ // that would also be valid for a fragment navigation.
+ bool is_fragment_navigation = urls_same_ignoring_fragment &&
+ (details.type == NAVIGATION_TYPE_IN_PAGE || details.is_in_page);
Java_WebContentsObserverAndroid_didNavigateMainFrame(
env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
- details.is_navigation_to_different_page(), in_page_navigation);
+ details.is_navigation_to_different_page(), is_fragment_navigation);
}
void WebContentsObserverAndroid::DidNavigateAnyFrame(
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc
index bcb3702..6d1c597 100644
--- a/content/browser/frame_host/navigation_controller_impl.cc
+++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -109,7 +109,7 @@ bool AreURLsInPageNavigation(const GURL& existing_url,
const GURL& new_url,
bool renderer_says_in_page,
NavigationType navigation_type) {
- if (existing_url == new_url)
+ if (existing_url.GetOrigin() == new_url.GetOrigin())
return renderer_says_in_page;
if (!new_url.has_ref()) {
diff --git a/content/browser/frame_host/navigation_controller_impl.h b/content/browser/frame_host/navigation_controller_impl.h
index 7ec82f3..7a06ba66 100644
--- a/content/browser/frame_host/navigation_controller_impl.h
+++ b/content/browser/frame_host/navigation_controller_impl.h
@@ -159,15 +159,11 @@ class CONTENT_EXPORT NavigationControllerImpl
// whether a navigation happened without loading anything, the same URL could
// be a reload, while only a different ref would be in-page (pages can't clear
// refs without reload, only change to "#" which we don't count as empty).
- bool IsURLInPageNavigation(const GURL& url) const {
- return IsURLInPageNavigation(url, false, NAVIGATION_TYPE_UNKNOWN);
- }
-
+ //
// The situation is made murkier by history.replaceState(), which could
// provide the same URL as part of an in-page navigation, not a reload. So
- // we need this form which lets the (untrustworthy) renderer resolve the
- // ambiguity, but only when the URLs are equal. This should be safe since the
- // origin isn't changing.
+ // we need to let the (untrustworthy) renderer resolve the ambiguity, but
+ // only when the URLs are on the same origin.
bool IsURLInPageNavigation(
const GURL& url,
bool renderer_says_in_page,
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 9bde501..6bb3d0e 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -2163,6 +2163,7 @@ TEST_F(NavigationControllerTest, InPage_Replace) {
params.gesture = NavigationGestureUser;
params.is_post = false;
params.page_state = PageState::CreateFromURL(url2);
+ params.was_within_same_page = true;
// This should NOT generate a new entry, nor prune the list.
LoadCommittedDetails details;
@@ -2214,6 +2215,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
params.gesture = NavigationGestureUnknown;
params.is_post = false;
params.page_state = PageState::CreateFromURL(url);
+ params.was_within_same_page = true;
// This should NOT generate a new entry, nor prune the list.
LoadCommittedDetails details;
@@ -3077,21 +3079,28 @@ TEST_F(NavigationControllerTest, IsInPageNavigation) {
main_test_rfh()->SendNavigate(0, url);
// Reloading the page is not an in-page navigation.
- EXPECT_FALSE(controller.IsURLInPageNavigation(url));
+ EXPECT_FALSE(controller.IsURLInPageNavigation(url, false,
+ NAVIGATION_TYPE_UNKNOWN));
const GURL other_url("http://www.google.com/add.html");
- EXPECT_FALSE(controller.IsURLInPageNavigation(other_url));
+ EXPECT_FALSE(controller.IsURLInPageNavigation(other_url, false,
+ NAVIGATION_TYPE_UNKNOWN));
const GURL url_with_ref("http://www.google.com/home.html#my_ref");
- EXPECT_TRUE(controller.IsURLInPageNavigation(url_with_ref));
+ EXPECT_TRUE(controller.IsURLInPageNavigation(url_with_ref, true,
+ NAVIGATION_TYPE_UNKNOWN));
// Navigate to URL with refs.
main_test_rfh()->SendNavigate(1, url_with_ref);
// Reloading the page is not an in-page navigation.
- EXPECT_FALSE(controller.IsURLInPageNavigation(url_with_ref));
- EXPECT_FALSE(controller.IsURLInPageNavigation(url));
- EXPECT_FALSE(controller.IsURLInPageNavigation(other_url));
+ EXPECT_FALSE(controller.IsURLInPageNavigation(url_with_ref, false,
+ NAVIGATION_TYPE_UNKNOWN));
+ EXPECT_FALSE(controller.IsURLInPageNavigation(url, false,
+ NAVIGATION_TYPE_UNKNOWN));
+ EXPECT_FALSE(controller.IsURLInPageNavigation(other_url, false,
+ NAVIGATION_TYPE_UNKNOWN));
const GURL other_url_with_ref("http://www.google.com/home.html#my_other_ref");
- EXPECT_TRUE(controller.IsURLInPageNavigation(other_url_with_ref));
+ EXPECT_TRUE(controller.IsURLInPageNavigation(other_url_with_ref, true,
+ NAVIGATION_TYPE_UNKNOWN));
// Going to the same url again will be considered in-page
// if the renderer says it is even if the navigation type isn't IN_PAGE.
@@ -3102,6 +3111,17 @@ TEST_F(NavigationControllerTest, IsInPageNavigation) {
// type is IN_PAGE.
EXPECT_TRUE(controller.IsURLInPageNavigation(url, true,
NAVIGATION_TYPE_IN_PAGE));
+
+ // If the renderer says this is a same-origin in-page navigation, believe it.
+ // This is the pushState/replaceState case.
+ EXPECT_TRUE(controller.IsURLInPageNavigation(other_url, true,
+ NAVIGATION_TYPE_UNKNOWN));
+
+ // Don't believe the renderer if it claims a cross-origin navigation is
+ // in-page.
+ const GURL different_origin_url("http://www.example.com");
+ EXPECT_FALSE(controller.IsURLInPageNavigation(different_origin_url, true,
+ NAVIGATION_TYPE_UNKNOWN));
}
// Some pages can have subframes with the same base URL (minus the reference) as
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index 054c6e8..bd39f04 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -619,7 +619,7 @@ public class ContentViewCore
mWebContentsObserver = new WebContentsObserverAndroid(this) {
@Override
public void didNavigateMainFrame(String url, String baseUrl,
- boolean isNavigationToDifferentPage, boolean isNavigationInPage) {
+ boolean isNavigationToDifferentPage, boolean isFragmentNavigation) {
if (!isNavigationToDifferentPage) return;
hidePopups();
resetScrollInProgress();
diff --git a/content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java b/content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java
index 17081e5..66e84ad 100644
--- a/content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java
+++ b/content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java
@@ -55,12 +55,12 @@ public abstract class WebContentsObserverAndroid {
* @param url The validated url for the page.
* @param baseUrl The validated base url for the page.
* @param isNavigationToDifferentPage Whether the main frame navigated to a different page.
- * @param isNavigationInPage Whether the main frame navigation did not cause changes to the
- * document (for example scrolling to a named anchor or PopState).
+ * @param isFragmentNavigation Whether the main frame navigation did not cause changes to the
+ * document (for example scrolling to a named anchor or PopState).
*/
@CalledByNative
public void didNavigateMainFrame(String url, String baseUrl,
- boolean isNavigationToDifferentPage, boolean isNavigationInPage) {
+ boolean isNavigationToDifferentPage, boolean isFragmentNavigation) {
}
/**
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index 45e8306..ca18244 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -150,7 +150,8 @@ void RenderViewHostTestHarness::Reload() {
DCHECK(entry);
controller().Reload(false);
static_cast<TestRenderViewHost*>(
- rvh())->SendNavigate(entry->GetPageID(), entry->GetURL());
+ rvh())->SendNavigateWithTransition(
+ entry->GetPageID(), entry->GetURL(), PAGE_TRANSITION_RELOAD);
}
void RenderViewHostTestHarness::FailedReload() {
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 9eb1eaa..98408fb 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -46,7 +46,7 @@ void TestRenderFrameHost::SendNavigateWithTransition(
void TestRenderFrameHost::SendFailedNavigate(int page_id, const GURL& url) {
SendNavigateWithTransitionAndResponseCode(
- page_id, url, PAGE_TRANSITION_LINK, 500);
+ page_id, url, PAGE_TRANSITION_RELOAD, 500);
}
void TestRenderFrameHost::SendNavigateWithTransitionAndResponseCode(
@@ -113,13 +113,19 @@ void TestRenderFrameHost::SendNavigateWithParameters(
params.gesture = NavigationGestureUser;
params.contents_mime_type = contents_mime_type_;
params.is_post = false;
- params.was_within_same_page = false;
params.http_status_code = response_code;
params.socket_address.set_host("2001:db8::1");
params.socket_address.set_port(80);
params.history_list_was_cleared = simulate_history_list_was_cleared_;
params.original_request_url = original_request_url;
+ url::Replacements<char> replacements;
+ replacements.ClearRef();
+ params.was_within_same_page = transition != PAGE_TRANSITION_RELOAD &&
+ transition != PAGE_TRANSITION_TYPED &&
+ url.ReplaceComponents(replacements) ==
+ GetLastCommittedURL().ReplaceComponents(replacements);
+
params.page_state = PageState::CreateForTesting(
url,
false,