Navigation fails on window.open() with empty URL from a hosted app |
|||
Issue descriptionWhat steps will reproduce the problem? (1) Go to a URL covered by an installed hosted app. I used https://drive.google.com/drive/my-drive with the Drive app installed (apdfllckaahabafndbhieahigkjlhalf) (2) Execute: var w = window.open('','_blank','width=500,height=500'); setTimeout(() => w.location = 'http://www.asdf.com', 0); What is the expected result? The popup opens and navigates to http://www.asdf.com/ What happens instead? Most of the time on a recent Linux release build, the popup opens and stays at about:blank. This was discovered internally as b/113914893. The problem here is that RenderFrameImpl::DecidePolicyForNavigation unnecessarily triggers an OpenURL IPC to the browser process. That's due to the should_fork logic in ChromeExtensionsRendererClient::ShouldFork(). Interestingly, it's not because of CrossesExtensionExtents(), which returns false due to the hosted apps workaround (should_consider_workaround) in CrossesExtensionProcessBoundary() (where the old_url corresponds to the hosted app and the new empty URL does not). Instead, it's due to this subsequent check: // If this is a reload, check whether it has the wrong process type. We // should send it to the browser if it's an extension URL (e.g., hosted app) // in a normal process, or if it's a process for an extension that has been // uninstalled. Without --site-per-process mode, we never fork processes for // subframes, so this check only makes sense for top-level frames. // TODO(alexmos,nasko): Figure out how this check should work when reloading // subframes in --site-per-process mode. if (!frame->Parent() && GURL(frame->GetDocument().Url()) == url) { if (is_extension_url != IsStandaloneExtensionProcess()) return true; } where the two URLs are the same (empty). Later on, in RFHI::OnOpenURL, the blank URL gets translated to "about:blank" by FilterURL. Note that if the repro had window.open('about:blank') instead, this wouldn't apply, due to this check in DecidePolicyForNavigation which skips the whole should_fork computation for target URLs that have the about: scheme: // Detect when we're crossing a permission-based boundary (e.g. into or out of // an extension or app origin, leaving a WebUI page, etc). We only care about // top-level navigations (not iframes). But we sometimes navigate to // about:blank to clear a tab, and we want to still allow that. if (!frame_->Parent() && !url.SchemeIs(url::kAboutScheme)) { ... compute should_fork ... } So, an 'about:blank' URL doesn't trigger OpenURL, but an empty URL does. Having the OpenURL IPC by itself shouldn't really be harmful, but it turns out that it creates a race with the subsequent navigation to asdf.com. Quoting nasko@'s description (with example.com being asdf.com in the repro above): "In the cases where it works correctly, the about:blank navigation started by OpenURL is waiting for the renderer to run the beforeunload handler and that takes longer than the start of the navigation to example.com. The start of example.com navigation cancels the existing about:blank navigation and it no longer commits and lets example.com finish navigating. In the failing case, the beforeunload handler executes quickly enough that it sends an ack to the browser process before the example.com navigation has started. This causes the browser process to send a commit IPC to the renderer for about:blank and while waiting for the commit IPC we start the navigation to example.com. When the commit for about:blank arrives, the example.com navigation is cancelled." A trivial fix would be to exclude empty URLs from the should_fork branch similarly to about: URLs, or find a way to translate the empty URL to about:blank sooner, but the better way is to clean up and remove ShouldFork altogether - see issue 883549.
,
Sep 14
I've got a CL in progress which should fix this: https://chromium-review.googlesource.com/c/chromium/src/+/1226075
,
Sep 14
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/d97d105fb1575487cfce16135bbc1faf9642e14b commit d97d105fb1575487cfce16135bbc1faf9642e14b Author: Alex Moshchuk <alexmos@chromium.org> Date: Fri Sep 14 23:24:25 2018 Remove hosted app reload logic from ShouldFork. This CL removes the logic that triggered process swaps in ChromeExtensionsRendererClient::ShouldFork() for the case when the main frame reloads a URL for which a hosted app was just installed or uninstalled. This logic isn't needed with --site-per-process, as that mode will already force a process transfer. This is covered by AppApiTest.ReloadIntoAppProcess and AppApiTest.ReloadIntoAppProcessWithJavaScript, which still pass with that logic removed. This CL also makes a fix on the browser side to keep this logic working even without --site-per-process, by unconditionally checking HasWrongProcessForURL() and forcing a process transfer if needed in IsRendererTransferNeededForNavigation(). This is possible because with PlzNavigate we will always go to the browser process and check for transfers, even without --site-per-process. With that fix, the above two tests also pass without --site-per-process. The above tweak also has a side effect of swapping processes when an app opens a cross-site, non-app popup (also made possible by work on issue 794315 ) in non-site-per-process mode, which seems acceptable and desirable - no reason for the cross-site popup to be in a process with app permissions. Bug: 883550 , 883549, 718516 Test: AppApiTest.ReloadIntoAppProcess and AppApiTest.ReloadIntoAppProcessWithJavaScript keep working, with and without --site-per-process. Change-Id: Ibac63fff3a36318fabceb593ca7ae7967eefad89 Reviewed-on: https://chromium-review.googlesource.com/1226075 Reviewed-by: Nasko Oskov <nasko@chromium.org> Reviewed-by: Devlin <rdevlin.cronin@chromium.org> Commit-Queue: Alex Moshchuk <alexmos@chromium.org> Cr-Commit-Position: refs/heads/master@{#591521} [modify] https://crrev.com/d97d105fb1575487cfce16135bbc1faf9642e14b/chrome/browser/ui/extensions/hosted_app_browsertest.cc [modify] https://crrev.com/d97d105fb1575487cfce16135bbc1faf9642e14b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc [modify] https://crrev.com/d97d105fb1575487cfce16135bbc1faf9642e14b/content/browser/frame_host/render_frame_host_manager.cc
,
Sep 21
I've confirmed that the repro in #0 is fixed on Mac Canary with r591521, and blois@ also confirmed that this fixes the internal repro, so marking as fixed. |
|||
►
Sign in to add a comment |
|||
Comment 1 by piatek@chromium.org
, Sep 13