Problem with Window.Location.assign(url)

6,773 views
Skip to first unread message

jarrod

unread,
Jul 16, 2008, 2:50:07 PM7/16/08
to Google Web Toolkit
My application has a page using a GWT module, such that the url is
something like:

http://my.domain.com/app-context/moduleA.html

The HTML in moduleA.html includes references to the module:
src="com.domain.my.ModuleA/com.domain.my.ModuleA.nocache.js"

Module A loads fine. It contains some code that requires a redirect to
moduleB.html, such that the url should become:

http://my.domain.com/app-context/moduleB.html

Similarly, Module B is all correctly referenced and loads up just
fine.
However, in ModuleA, when I call the following:

Window.Location.assign("moduleB.html")

The browser is redirected to:
http://my.domain.com/app-context/com.domain.my.ModuleA/moduleB.html

In effect, the location redirect is doing so relative to the current
module's source JS file, not the browser's current URL.

I looked at the source for Window.Location, and all I can wonder is
"WTF"?

I cannot hard code the complete target URL, as my application runs on
different domains and under different contexts. I should be able to
redirect to a relative page easily enough, right? What's going wrong?



P.S. using GWT 1.5 RC1

jarrod

unread,
Jul 16, 2008, 2:57:18 PM7/16/08
to Google Web Toolkit
This is even stranger. Observe the following EntryPoint code:

public void onModuleLoad() {
RootPanel.get().add(new Button("Redirect", new ClickListener()
{
public void onClick(Widget sender) {
Window.Location.assign("index.html");
}
}));
RootPanel.get("root").add(root);
}

Click the button, and you get successfully redirected from "/context/
module.html" to "/context/index.html", just like you would expect.

However, given this code (never mind the redirect in module load, it's
just to illustrate a point):

public void onModuleLoad() {
Window.Location.assign("index.html");
}

You are incorrectly redirected from "/context/module.html" to "/
context/com.domain.my.Module/index.html"


So what's going on?

Thomas Broyer

unread,
Jul 16, 2008, 5:47:25 PM7/16/08
to Google Web Toolkit


On Jul 16, 8:57 pm, jarrod <jarrod.carl...@gmail.com> wrote:
> This is even stranger. Observe the following EntryPoint code:
>
>     public void onModuleLoad() {
>         RootPanel.get().add(new Button("Redirect", new ClickListener()
> {
>             public void onClick(Widget sender) {
>                 Window.Location.assign("index.html");
>             }
>         }));
>         RootPanel.get("root").add(root);
>     }
>
> Click the button, and you get successfully redirected from "/context/
> module.html" to "/context/index.html", just like you would expect.

The onClick method is called in response to the button's click, and
the button lies in the /context/moduleA.html, so this URL is used as
the "base URL" for resolving relative URLs.

> However, given this code (never mind the redirect in module load, it's
> just to illustrate a point):
>
>     public void onModuleLoad() {
>         Window.Location.assign("index.html");
>     }
>
> You are incorrectly redirected from "/context/module.html" to "/
> context/com.domain.my.Module/index.html"
>
> So what's going on?

onModuleLoad is called by the *.cache.html page, which in your case
lies in /context/com.domain.my.Module, which is thus used as the base
URL, hence the result.

In a few words: the "calling context" is used to retrieve a base URL.

To cater for these cases, GWT has GWT.getHostPageBaseURL() and
GWT.getModuleBaseURL() methods, that you prepend to your relative URL.

jarrod

unread,
Jul 17, 2008, 9:45:24 AM7/17/08
to Google Web Toolkit
I've been working with JavaScript for some time, now, and I have never
seen JavaScript be "aware" of the location from which it was loaded.

The hosting page is located at "/context/moduleA.html" so if I add my
own location-setting javascript in the page as such:

function go() {
window.location="moduleB.html";
}

<body onload="go()">...</body>

Where do you think that would redirect you to? Why would GWT ever have
as a base url anything other than the host page url?


-Puzzled

Benoit S

unread,
Mar 14, 2012, 5:58:26 AM3/14/12
to google-we...@googlegroups.com, Google Web Toolkit
We also encountered this problem with GWT 2.4. To complete previous messages, we also noticed that it depends on the calling context. But when the calling context is an event handler, all browsers don't have the same behavior (we have the expected behavior on all browsers but IE any version).

It sounds like the problem comes from the fact that GWT code is in an iframe and relative path resolution is done using the calling context whereas we could expect GWT to resolve it in the main window context since the fact that code is in a iframe is hidden to user.

Here is a GWT code snippet that shows the problem:
public class IERedirectBug
    implements EntryPoint
{
    @Override
    public void onModuleLoad()
    {
        final Button redirectButton = new Button("Relative Redirection");

        RootPanel.get().add(redirectButton);

        redirectButton.addClickHandler(new ClickHandler()
        {
            @Override
            public void onClick(ClickEvent event)
            {
        // Works with all browsers but IE
                Location.assign("target.html");
            }
        });
    }
}

To investigate the problem we did several test cases in pure Javascript.

In the first case, we use a frame that is in a subfolder and that contains a function (as the GWT frame contains code) that does the main page redirection (window.parent.location.assign()). If we call this code from the main window (case #1), all browsers resolve correctly relative paths. If this code is called from the iframe (next to the function declaration, case #2), all browsers resolve the relative path according to the iframe location and not the main page location. This shows that calling context impacts relative path resolution and all browsers seem to have the same behavior (at least Google Chrome and IE 8 & 9 on which we really tested).

Main window (test.html):
<!DOCTYPE html>
<html>
<head></head>

<body>
  <iframe src="folder/frame.html" id="frame"> </iframe>
  <h1>main</h1>
  <button>redirect</button>
</body>
</html>

Iframe (folder/frame.html):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <h1>test2</h1>
  <script type="text/javascript">
    function redirect()
    {
          window.parent.location.assign('target.html');
    }
  </script>
</body>
</html>

In case #1, we add to the button declaration in test.html the call to the redirect function: <button onclick="document.getElementById('frame').contentWindow.redirect()">redirect</button>. This redirects to target.html on any browser, the expected behavior.
In case #2, we call the redirect function from the frame, just after its declaration:
  function redirect()
    {
          window.parent.location.assign('target.html');
    }
  redirect();
It redirects to folder/target.html on any browser.

These examples simply confirm that calling context impacts relative path resolution but don't explain why IE hasn't the same behavior as other browsers in our GWT case.

So we tried to reproduce in a pure Javascript example the way GWT handles events (through the global handler), case #3. This way enabled us to reproduce the problem. For modern browsers and IE9, the standard global event handling system is used throw $wnd.addEventListener(). For IE 8 it's a specific code (case #4). But whatever global event handling system is used, Location.replace() and Location.assign() don't have the expected behaviour with relative paths on IE.

In case #3, we use this code (just after redirect function declaration):
// Works on any browser but IE9
window.parent.addEventListener('click', function(e) { redirect(); }, true);

In case #4 (IE8), we use this code:
window.parent.document.body.attachEvent('onclick', function(e) { redirect(); });

Cases #3 and #4 show that with global handler, IE has the same behavior as case #2 while other browsers work as in case #1, which is the expected behavior.

Even if the problem can be solved by API users using GWT.getModuleBaseURL(), don't you think it sould be fixed in GWT itself since it doesn't respect the GWT "execution doesn't depend on browser" principle?
I guess it could be solved by analyzing the parameter given to the assign() method. If it starts neither with a protocol (http:// for instance) nor with a slash, we can consider it's a relative path (unless I forget cases) and thus prefix it with GWT.getModuleBaseUrl().

Jaroslav Záruba

unread,
Dec 8, 2012, 12:39:59 AM12/8/12
to google-we...@googlegroups.com, Google Web Toolkit
i have create an issue report for this baby
Reply all
Reply to author
Forward
0 new messages