New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 818363 link

Starred by 2 users

Issue metadata

Status: Available
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug

Blocking:
issue 740783



Sign in to add a comment

OpenBookmarkApp() may no longer preserve window.opener in non-initial navigations

Project Member Reported by alex...@chromium.org, Mar 3 2018

Issue description

I'm filing this as a followup to https://chromium-review.googlesource.com/c/chromium/src/+/881836.  Once that CL lands, we will swap BrowsingInstances on certain browser-initiated navigations, such as via the omnibox or bookmarks.  A new BrowsingInstance means that scripting relationships with other tabs (e.g., window.opener) will be severed.  This is desirable to prevent unwanted process sharing in  issue 803367 .

I noticed that some code used by bookmark apps / desktop PWA in BookmarkAppNavigationThrottle::OpenInAppWindowAndCloseTabIfNecessary may be problematic after my CL lands [1].  If an existing tab/app does a window.open() to a URL covered by a bookmark app, and the window.open() targets a new window, we're ok: ReparentWebContentsAndResume() will reparent the new WebContents into an app Browser and continue the existing renderer-initiated navigation there.  (In fact, this was just recently fixed by ortuno@'s https://chromium-review.googlesource.com/923902.) 

However, I think we should check what happens if window.open() targets an *existing* window (e.g., by name as in window.open(url, "name")), in which case we call OpenBookmarkApp(), which cancels the existing renderer-initiated navigation and restarts it as a browser-initiated, AUTO_BOOKMARK navigation in a new (app) WebContents. (Page transition set here: [2].)  As a result, we can't distinguish this from a user clicking on a regular bookmark and swap BrowsingInstances, which breaks window.opener.  I'm not actually sure if we want to preserve the opener in that case -- I saw issue 804881, but the scenario here is a bit different: maybe something like a tab trying to navigate a window with app1 to another app2, which results in opening a new window for app2.  I'm not sure if there are other scenarios in which OpenBookmarkApp() needs to be used - currently this isn't covered by any tests.  But if it's desirable app2 to preserve the window.opener, we'll need to find a way to tell RenderFrameHostManager::IsBrowsingInstanceSwapAllowedForPageTransition() to not swap BrowsingInstances in this case.

The latter might be tricky: we could skips BrowsingInstance swaps in app windows, but at the time this function is called (as part of chrome::Navigate()), the is_app() bit on Browser is not updated yet -- that happens later when Browser actually adds the WebContents to its tab strip, which happens after navigating.  Changing those navigations to something other than AUTO_BOOKMARK is probably undesirable per https://chromium.googlesource.com/chromium/src/+/f3a29a53dd05161c7e9a36f1cd55497cc2ab0239.  Bookmark app URLs don't use app/extension processes so we can't check for effective URLs either.  So some investigation is needed to find a good way to plumb information about these cases, if we care about them.

Ideally, we would just get rid of OpenBookmarkApp() altogether, and always use the path in ReparentWebContentsAndResume().  Restarting a renderer-initiated navigation as a browser-initiated navigation seems fishy, so ideally we would just never do it.  Not sure if that's feasible though.

[1] https://cs.chromium.org/chromium/src/chrome/browser/extensions/bookmark_app_experimental_navigation_throttle.cc?l=473&rcl=ef8c76c0202de4b984bccf82e67a6b21329a81be

[2]
https://cs.chromium.org/chromium/src/chrome/browser/ui/extensions/application_launch.cc?l=212&rcl=8292a417e26eb076cbbbbe7403edc1e6b994ba35
 
Blocking: 740783
Components: UI>Browser>WebAppInstalls
Thanks for opening this bug! That is a case we hadn't considered :/

Code in BookmarkAppNavigationThrottle (now BookmarkAppExperimentalNavigationThrottle) is for link capturing, a feature which we recently separated from Desktop PWAs launch, so no need to block anything on it.

It's unclear what the main use case for the feature will be so the importance of fixing this is unclear. I'll mark it as blocking Issue 740783 so we revisit once we have a clearer picture of the feature.

> Ideally, we would just get rid of OpenBookmarkApp() altogether, and always use the path in ReparentWebContentsAndResume().

OpenBookmarkApp() is for cross-site navigations. Always reparenting the WebContents would result in an odd UX. For example, if a user is on the Google app and clicks a link to Twitter, and we reparent the WebConrtents, it'll seem as if we had closed the Google App and opened the Twitter app instead. 

> at the time this function is called (as part of chrome::Navigate()), the is_app() bit on Browser is not updated yet.

That is strange. I was under the impression that setting a Browser as an "App Browser" could only be done at Browser construction time. is_app() is implemented as

!app_name_.empty()

And app_name_ can only be set through CreateParams at construction time[1].


[1] https://cs.chromium.org/chromium/src/chrome/browser/ui/browser.cc?sq=package:chromium&dr&l=379
Thanks for the additional context! 

> That is strange. I was under the impression that setting a Browser as an "App Browser" could only be done at Browser construction time. is_app() is implemented as

Sorry, I was not precise.  You're right that the Browser app_name_ is set at creation time (in this case, in OpenApplicationWindow()), and this is what is_app() is based on.  What I observed was that during chrome::Navigate(), when we make the decision about which process to use for the navigation (RenderFrameHostManager::DetermineSiteInstanceForURL), calling out to Browser from the WebContents (via WebContentsDelegate) and then checking is_app() there returns *false* for the OpenBookmarkApp() path.  This seemed strange, and I haven't looksed closely, but I suspect that's because the WebContents created in chrome::Navigate is initially owned by a ScopedTargetContentsOwner inside that function, and it only becomes associated with the app Browser when it calls params->browser->tab_strip_model()->AddWebContents() (probably here: [1]), which happens after the navigation has already been kicked off by LoadURLInContents().

[1] https://cs.chromium.org/chromium/src/chrome/browser/ui/browser.cc?l=971&rcl=caf69fed21cab23246f1c7c4940154ea21f7641f


Sign in to add a comment