Closed Bug 1044950 Opened 10 years ago Closed 10 years ago

Window.open() doesn't resolve relative url correctly when iframe involved

Categories

(Core :: DOM: Core & HTML, defect)

33 Branch
x86_64
Linux
defect
Not set
normal

Tracking

()

RESOLVED INVALID

People

(Reporter: duanyao.ustc, Unassigned)

Details

Attachments

(1 file)

Attached file iframe-open.zip
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:33.0) Gecko/20100101 Firefox/33.0 (Beta/Release)
Build ID: 20140703030200

Steps to reproduce:

Assume there are 2 html documents in different directories, e.g. outer.htm and inner/inner.htm, and the latter is embed into the former via an iframe.

Call frames[0].open('inner.htm') in the context of outer.htm.

(You can unzip the attachment, open outer.htm, and click "open via inner" button.)



Actual results:

The popup window can't load inner.htm, because the relative url 'inner.htm' passed to open() is resolved against outer.htm, not inner.htm.


Expected results:

Url 'inner.htm' should be resolved against inner.htm.

According to the spec (http://www.w3.org/TR/html5/browsers.html#dom-open),

    the argument (first arg of window.open) must be resolved to an absolute URL
   (or an error), relative to the API base URL specified by the entry settings object
   when the method was invoked.

If I understand it right, the "API base URL" is the url to inner.htm when calling frames[0].open(...).
P.S., if execute frames[0].open('inner.htm') in the devtools console, the url 'inner.htm' is correctly resolved, strange.
> If I understand it right, the "API base URL" is the url to inner.htm

No, it's the base url of the window where script was first entered, since it's using the _entry_ settings object.

In the case of the attached testcase, when clicking "open via inner" the "API base URL" will be that of outer.htm.  When clicking "open myself" it will be that of inner.htm.

This admittedly odd behavior is quite necessary for web compat and interoperable across all browsers last I checked, which is why the spec requires it.

> P.S., if execute frames[0].open('inner.htm') in the devtools console,

Then the script entry point is the devtools console, not either of inner.htm or outer.htm (this is arguably a bug in the devtools console; it should make the entry point be outer.htm).  It just so happens that in the case when the entry point is not associated with any window at all we fall back on using the window the open() call happened on for the base URI, which is why it ends up working.

It might be worth filing a devtools bug here.
Status: UNCONFIRMED → RESOLVED
Closed: 10 years ago
Resolution: --- → INVALID
(In reply to Boris Zbarsky [:bz] from comment #2)
Thank for the explanation. However, when I tried to figure out a workaround for this unforturnate API, I found another issue with window.open().

Replace "frames[0].open('inner.htm')" in outer.htm with following codes.

This code works in FF, Chrome, and IE:
    frames[0].setTimeout(frames[0].open, 0, 'inner.htm') //1

But this code only works in Chrome and IE, still fail the same way in FF:
    frames[0].setTimeout(open, 0, 'inner.htm') //2

As you said, "API base URL" is the base url of the window where script was first entered (in this case, frames[0]), so I think  it should be irrelavent which open() function is actually called, right?
And this code works in FF, but not in Chrome and IE:
    setTimeout(frames[0].open, 0, 'inner.htm') //3

So it seems FF only concerns about where the first argument of setTimeout() is defined, while Chrome and IE only concern about where setTimeout() is defined. Which one is correct? I'm confused.
That part wasn't defined in a spec until recently, which is why browsers disagree, but I believe the Firefox behavior there is the right one: when invoking a callback the entry settings global is the global of the callback.
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: