Closed Bug 744451 Opened 12 years ago Closed 12 years ago

Handle window.open in <iframe mozapp>

Categories

(Firefox OS Graveyard :: General, defect)

x86
macOS
defect
Not set
normal

Tracking

(blocking-kilimanjaro:+, blocking-basecamp:+)

RESOLVED DUPLICATE of bug 742944
blocking-kilimanjaro +
blocking-basecamp +

People

(Reporter: mhanson, Unassigned)

References

Details

Some issues came up in bug #742944 about how b2g should handle window.open.  That bug is for issues specific to the browser.

window.open needs to behave sensibly in app mode, so that apps can use Twitter, Facebook, GoogleID, PayPal X, etc.

Specifically, we need to make sure the interactions are sensible, that inter-window messaging (including postMessage, focus(), and close() work), and that the UI affords some anti-phishing protection.

We've already seen some breakage on desktop because of this, in bug #729853, and bug #719175.  We'll need a proposal for how it should behave, a security review on that, and whatever changes are needed to make it all go.

See the discussion in #742944 for a high-level intro to security issues.
I'm concerned that we may be designing b2g app window.open around the needs of 3rd-party auth without considering the other implications.

That is to say, in general, I don't think an app wants window.open to open a modal window with a URL bar and SSL indicator.  In general, cross-origin window.open should probably go to the browser, and  apps probably just shouldn't do same-origin window.open.

I don't mean to say that we should punt on 3rd-party auth, just that we should consider how 3rd-party auth fits in to a bigger picture.
> In general, cross-origin window.open should probably go to the browser,

This would match how links with |target=_blank| would likely work.
Yep, totally agree that we should figure out something better.  But this is huge source of pain for app developers on both native and web platforms, and punting to the browser will create more problems than it solves.

See, for example:
http://sites.google.com/site/oauthgoog/oauth-practices/auto-detecting-approval

In which the "best practices" for how to detect the completion of an OAuth flow include running a local web server, monitoring cookies, using a browser extension, and monitoring the web browser's title.

If we punt window.open to the browser, I think we'll be driving app developers to embed a <browser> element and drive 3rd-party interactions themselves - which forks their app implementation from the web.  Not saying I have a good answer yet, but we need to puzzle this one out.
Here's some Gaia UX team thoughts on this. Grain of salt: the technical details are largely unfamiliar to me. I'm speaking from general mobile UX best practices standpoint.

From #742944:
"There's no reason FB connect couldn't run in an iframe, right?" 

My suggestion as well. Every mobile OS provides web views of some sort. Open Flipboard on an iPad, and select "Login to Facebook". The FB Connect UI opens in a webview, within the app. 

The alternative—opening the window in the default browser, and then returning the user to the parent app once the login was complete—would be terrible UX. Suspicious as well, to the average user. "Why am I being asked into a random website> Must be a scam..." 

Bottom line, meta conversation: the rules for mobile are different than the rules for desktop. Spawning windows Just Isn't Done. It's one window per app. The only exception is throwing hyperlinks to default browser if parent app doesn't handle them inline (eg: click on URL in an email).
> "There's no reason FB connect couldn't run in an iframe, right?" 

Well, Mike pointed out that there are phishing issues here (you can't see the URL loaded into an iframe like you can see the URL of a popup), and that FB connect doesn't even allow itself to run in an iframe.
"Well, Mike pointed out that there are phishing issues here (you can't see the URL loaded into an iframe like you can see the URL of a popup)..."

So how do iOS, Android, etc solve this? There's _tons_ of prior art here, at least in terms of UX and security, no?

"...and that FB connect doesn't even allow itself to run in an iframe."

No ideas there :)
(In reply to Josh Carpenter from comment #6)
> "Well, Mike pointed out that there are phishing issues here (you can't see
> the URL loaded into an iframe like you can see the URL of a popup)..."
> 
> So how do iOS, Android, etc solve this? There's _tons_ of prior art here, at
> least in terms of UX and security, no?

I'm no smartphone addict, so I don't know first-hand, but you alluded to one answer yourself in comment 4:

> The FB Connect UI opens in a webview, within the app.

So...there's no authentication that you're actually logging in to FB.  I imagine FB doesn't framebust because the webview is a top-level frame.  I have no idea how the app gets the authentication token out of the webview, but it's probably just a cookie...

None of this works if you're a webpage, of course, because the iframe isn't a top-level frame.  We could fake it -- that's what mozbrowser does, after all -- but letting a page frame any site would have pretty serious security implications.

Anyway if we're suggesting an auth scheme which is in any way different from what pages use right now, then we can do basically whatever we want, and we can forgetabout window.open.
"I'm no smartphone addict, so I don't know first-hand, but you alluded to one answer yourself in comment 4:" 

Heh, yes, was alluding to that. Basically saying, it seems like common practice in mobile OS's.

"None of this works if you're a webpage, of course, because the iframe isn't a top-level frame.  We could fake it -- that's what mozbrowser does, after all -- but letting a page frame any site would have pretty serious security implications."

There's the rub. I think iOS deals with it by saying, "We give you this power. But don't abuse it. Obey this set of rules. If you break them, you don't get past the bouncer (App Store approval process)." 

We're in the process of defining rules for apps (thou shalt provide a manifest, thou shalt declare which permissions you need, thou shalt include an icon, etc). Can we add a rule for this? And then enforce in Mozilla Marketplace submission process? Doesn't provide unscrupulous side-loaded (eg: installed direct from site) situations, but helps contain the threat at least.
Maybe in a <iframe mozapp> context window.open is not allowed or it should only open a page in the browser app. We should think of other window methods that would not be allowed in a 'mozapp' context. 
Anyway, I think we do need a mechanism to support OAuth 1.0 and 2.0 flows. My proposal, to tackle the bad UX Josh is mentioning, is that instead instead of calling window.open (which would be prohibited) I would create a new iframe mozbrowser in the DOM and trigger an animation / transition to show it smoothly to the user asking for the credentials on the third party site. Once the user completes the authentication process such an iframe could be killed and return smoothly to the original app context. Using this mechanism would make things IMO more consistent from UX point of view.
There's a relevant discussion going on in bug 752666.
Justin and I had a really good chat about this.  I think we tentatively agreed on a mechanism to prototype, but not 100% on the bigger picture.  The mechanism first though
 - window.open first goes through the normal popup-blocker checks.  If it passes,
 - in mozapp, Gecko specially handles window.open.  It does *not* create a new "native widget".  Instead,
 - Gecko proxies the window.open call into the context of the "embedder" (the web app that serves as window manager, the code that handles app.launch() calls).
 - (details here are fuzzier, but approximately) Gecko pre-creates a special iframe that is bound to the OS process of the window.open caller.  The iframe is configured so that it shares the window.open caller's data store.
 - the "embedder" is handed the iframe, unstyled and unloaded, along with the other window.open parameters (requested size, etc.)
 - the embedder can accept or reject the iframe.  Details TBD.
 - if it accepts the popup, the embedder can style it however it wants.

This effectively punts the decision out of Gecko and into the window manager, but without getting into messy issues with "native widgets".

In Gaia, on phone-sized screens, we would likely only allow one popup to be open at any time.  We would most likely ignore the size etc params requested by the window.open caller and instead draw it at a fixed size and position.  We would draw UI to show the URL of the popup and an SSL indicator.  The popup would be treated like a Firefox "tab-modal" popup, and would be hidden when the app was switched out of focus. (We could allow focus to be returned to the app, but it's not clear how focus could later be returned to the popup window if we did that.)

From our discussion, the remaining questions, other than technical details above, are
 - should we create a new magic window name like "_auth" and only accept popups for that name?  (Along with a whitelist.)  My vote is "no".
 - should rejected popups instead be routed to the browser app?  My vote is "no".

However, both of those questions only concern the gaia window manager, so it's very easy to change our minds later.
(In reply to Chris Jones [:cjones] [:warhammer] from comment #11)
> (We could allow focus to be returned
> to the app, but it's not clear how focus could later be returned to the
> popup window if we did that.)
> 

This was probably a bit confusing in context, but what I meant was, while the "app-and-popup" are displayed as the "focused window", we could decide or not to allow the user to tap on the app and hide the popup.  If we did allow that, we'd probably want some way to restore the popup, which gets complicated.  We'd probably want to reserve tap-outside-popup as a gesture that dismissed the popup.

And if we did *that*, we might want to draw the app content with lower opacity while the popup is open.
Nice work. I had a to-do this weekend to nudge this conversation along. :)

"...while the "app-and-popup" are displayed as the "focused window", we could decide or not to allow the user to tap on the app and hide the popup." ——— I would prefer Not, and instead use an explicit "close" button (either provided by the popup's content, or part of the popup's standard styling).

FWIW, I believe what you're describing is analogous to Android ICS's popups? http://developer.android.com/design/building-blocks/dialogs.html#popups
Yeah, I think something like that.
Just a heads-up that due to our integration with PayPal and BrowserID, not having window.open with cross-window postMessage (or a reasonable equivalent) blocks Marketplace from functioning on b2g.
The hack I've come to accept we'll have to do is to allow one modal window per app, and have some UI around it showing the URL of the popup window.

We are not going to implement a general window manager in apps.  Just not going to happen.  One modal popup is ugly enough.
(In reply to Potch [:potch] from comment #15)
> Just a heads-up that due to our integration with PayPal and BrowserID, not
> having window.open with cross-window postMessage (or a reasonable
> equivalent) blocks Marketplace from functioning on b2g.

That's pretty much the only reason we're bothering with this for phone-style window managers.
Whiteboard: [b2g:blocking+]
Depends on: 742944
nominating for triage.  Discussion in bug 742944 comment 33
blocking-basecamp: --- → ?
blocking-kilimanjaro: --- → ?
Definitely a k9o and basecamp nom - this is a key implementation needed for this user story:

P1: The ability to sign into application using:

    Persona ID, Google ID, Facebook ID, Twitter ID, Brazil-specific IDs, Marketplace
    This requirement gives B2G the ability to support in-app purchases
blocking-kilimanjaro: ? → ---
blocking-kilimanjaro: --- → ?
blocking-basecamp: ? → +
blocking-kilimanjaro: ? → +
Whiteboard: [b2g:blocking+]
This is going to be fixed by bug 742944.  It's exactly the same code, since mozapp is (largely) a functional subset of mozbrowser.  There's no use tracking these bugs separately.
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → DUPLICATE
No longer depends on: 762049
No longer depends on: 766481
No longer depends on: 742944
You need to log in before you can comment on or make changes to this bug.