From: Leif Åstrand Date: Fri, 2 Aug 2013 07:20:40 +0000 (+0300) Subject: Refine handling of null and empty URI fragments (#12207) X-Git-Tag: 7.1.2~4 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d97cfbc9a1409582bbe4456f08f648921b7e3300;p=vaadin-framework.git Refine handling of null and empty URI fragments (#12207) Change-Id: Ie133694b010a586c6336e9b04be7bcd94d2525e9 --- diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index 45b0a7ab9d..c6d2e1436b 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -40,6 +40,7 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.History; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.Window.Location; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.google.web.bindery.event.shared.HandlerRegistration; @@ -352,14 +353,30 @@ public class UIConnector extends AbstractSingleComponentContainerConnector if (uidl.hasAttribute(UIConstants.LOCATION_VARIABLE)) { String location = uidl .getStringAttribute(UIConstants.LOCATION_VARIABLE); + String newFragment; + int fragmentIndex = location.indexOf('#'); if (fragmentIndex >= 0) { // Decode fragment to avoid double encoding (#10769) - getWidget().currentFragment = URL.decodePathSegment(location + newFragment = URL.decodePathSegment(location .substring(fragmentIndex + 1)); + + if (newFragment.isEmpty() + && Location.getHref().indexOf('#') == -1) { + // Ensure there is a trailing # even though History and + // Location.getHash() treat null and "" the same way. + Location.assign(Location.getHref() + "#"); + } + } else { + // No fragment in server-side location, but can't completely + // remove the browser fragment since that would reload the page + newFragment = ""; } - if (!getWidget().currentFragment.equals(History.getToken())) { - History.newItem(getWidget().currentFragment, true); + + getWidget().currentFragment = newFragment; + + if (!newFragment.equals(History.getToken())) { + History.newItem(newFragment, true); } } diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java index 3656309be5..037d8e8352 100644 --- a/server/src/com/vaadin/server/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -552,10 +552,11 @@ public class Page implements Serializable { * The fragment is the optional last component of a URI, prefixed with a * hash sign ("#"). *

- * Passing null as newFragment clears the fragment - * (no "#" in the URI); passing an empty string sets an empty fragment (a - * trailing "#" in the URI.) This is consistent with the semantics of - * {@link java.net.URI}. + * Passing an empty string as newFragment sets an empty + * fragment (a trailing "#" in the URI.) Passing null if there + * is already a non-null fragment will leave a trailing # in the URI since + * removing it would cause the browser to reload the page. This is not fully + * consistent with the semantics of {@link java.net.URI}. * * @param newUriFragment * The new fragment. @@ -570,6 +571,11 @@ public class Page implements Serializable { */ public void setUriFragment(String newUriFragment, boolean fireEvents) { String oldUriFragment = location.getFragment(); + if (newUriFragment == null && getUriFragment() != null) { + // Can't completely remove the fragment once it has been set, will + // instead set it to the empty string + newUriFragment = ""; + } if (newUriFragment == oldUriFragment || (newUriFragment != null && newUriFragment .equals(oldUriFragment))) { diff --git a/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.html b/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.html index bcb9f52afe..ba24b55f64 100644 --- a/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.html +++ b/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.html @@ -71,7 +71,66 @@ vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0] Current URI fragment: test - + + + open + /run/ + + + + open + /run/com.vaadin.tests.components.ui.UriFragmentTest?restartApplication + + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + No URI fragment set + + + click + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0] + + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + No URI fragment set + + + click + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0] + + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + Current URI fragment: + + + click + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0] + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + Current URI fragment: test + + + click + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0] + + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + Current URI fragment: + diff --git a/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.java b/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.java index 2172b00ee3..bfd784280a 100644 --- a/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.java +++ b/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.java @@ -29,6 +29,21 @@ public class UriFragmentTest extends AbstractTestUI { getPage().setUriFragment("test"); } })); + + addComponent(new Button("Navigate to #", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + getPage().setUriFragment(""); + } + })); + + addComponent(new Button("setUriFragment(null)", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + getPage().setUriFragment(null); + } + })); } private void updateLabel() {