UNCONFIRMED 23432
window.open scripts do not trigger newWindowDelegate callback.
https://bugs.webkit.org/show_bug.cgi?id=23432
Summary window.open scripts do not trigger newWindowDelegate callback.
Dirk Theisen
Reported 2009-01-20 07:54:50 PST
By WebKit delegate implements - (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener; It gets called for href links an target set, but not for javascript window.open(url) links. Instead, a new window is silently requested and the new url is requested to load into that new window. I'd expect the above delegate to be called prior to new window/frame generation with the url given in the window.open call. In addition, on window.open the delegate method - (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request gets passed a nil request which makes it impossible to take appropriate action as a workaround. This might qualify for a different bug.
Attachments
Simple test case, that show new-window-policy-decision-requested is not emited on JS window.open() (4.01 KB, text/x-csrc)
2010-10-14 14:53 PDT, Juan Pablo Ugarte
no flags
[PATCH 1/4] Allow creating hidden window (3.18 KB, patch)
2010-11-09 14:21 PST, Nicolas Dufresne
no flags
[PATCH 2/4] Show window only after initial location request (5.02 KB, patch)
2010-11-09 14:22 PST, Nicolas Dufresne
no flags
[PATCH 3/4] Don't duplicate code from FrameTree::find() (5.47 KB, patch)
2010-11-09 14:22 PST, Nicolas Dufresne
no flags
[PATCH 4/4] Trigger newWindowDelegate when window.open() is called (7.65 KB, patch)
2010-11-09 14:23 PST, Nicolas Dufresne
no flags
Patch (15.65 KB, patch)
2010-11-29 22:32 PST, Nicolas Dufresne
abarth: review-
Joone Hur
Comment 1 2010-03-21 06:24:07 PDT
In WebKitGtk port, "new-window-policy-decision-requested" signal isn't also triggered when using the window.open call. It seems like a bug.
Lucas De Marchi
Comment 2 2010-05-27 21:47:37 PDT
(In reply to comment #1) > In WebKitGtk port, "new-window-policy-decision-requested" signal isn't also triggered when using the window.open call. > It seems like a bug. For javascript it will call ChromeClient::createWindow() instead. In EFL port I've implemented both ChromeClientEfl::createWindow() and ChromeClient::decidePolicyForNewWindowAction() by calling our ewk_view_window_create() with different parameters in order to be able to differentiate between javascript ones and link ones. Unfortunately, sending upstream this code is being blocked by other bugs that are not reviewed yet. As soon as they are r+ cq+ I'll send them.
Juan Pablo Ugarte
Comment 3 2010-10-14 14:53:23 PDT
Created attachment 70783 [details] Simple test case, that show new-window-policy-decision-requested is not emited on JS window.open()
Nicolas Dufresne
Comment 4 2010-10-18 12:03:51 PDT
For the record, this has something to do with a fixme in JSDOMWindowCustom.cpp line 678: // FIXME: It's much better for client API if a new window starts with a URL, here where we // know what URL we are going to open. Unfortunately, this code passes the empty string // for the URL, but there's a reason for that. Before loading we have to set up the opener, // openedByDOM, and dialogArguments values. Also, to decide whether to use the URL we currently // do an allowsAccessFrom call using the window we create, which can't be done before creating it. // We'd have to resolve all those issues to pass the URL instead of "".
Nicolas Dufresne
Comment 5 2010-10-19 11:14:59 PDT
After more analyses, I concluded that this missing newWindowDelegate callback hides a bigger problem. The problem is that checking the window policy is an asynchronous call but window.open() calls are handled synchronously. From my point of view, if new window is denied by the client, window.open() should return undefined. This cannot be achieved with current API. As exposed by Lucas, one solution is to check the policy when ChromeClient::createWindow() is called. I'm currently writing a patch for the Gtk platform. There is other issues that will need fixing before it actually work. 1. The FrameLoadRequest passed to createWindow() always contains an empty URL (""). 2. There is only NavigationTypeOther that seems to fit, maybe a NavigationTypeJavascript would be better. (optional I guess)
Nicolas Dufresne
Comment 6 2010-10-19 13:07:31 PDT
(In reply to comment #5) > I'm currently writing a patch for the Gtk platform. There is other issues that > will need fixing before it actually work. Sorry for replying to my own comment, but it's not possible to implement the check in Gtk's ChromeClient::createWindow(). The reason is that Gtk port allow to queue the decisions for later. I've compared window.open() with other similar API like history.go() and found that they all return void which make it simple to delay their execution. For window.open(), the return value is a JavaScript Window object, which is currently bound at creation time to the native frame/page object. This function is implemented as one synchronous native call, and thus cannot be interrupted and resumed later. Base on these facts, I think a potential solution would be to delay the creation of native frame until the navigation policy decision has been taken. The side effect is that call to window.open() will return a JavaScript window even if the window creation is denied. Is this acceptable ?
Nicolas Dufresne
Comment 7 2010-11-09 08:52:59 PST
After more work on this I've finally managed to implement a solution that I will soon attach. The solution I've found is to allow creating page without making it visible (see Page::chrome().show() and WebCore::createWindow()). This enables two things: 1) you can actually request for location change before displaying the window, which allow making popup blocking decision/triage based on URI before the window is displayed and 2) for synchronous scripted popup (e.g. window.open()), you can simply create an hidden window, fire NewWindowPolicy on initial location change and show only if decision was positive (close if not). At first I was concern about show() call being flipped with ChangeLocationPolicy, but I found that there exist cases where we already get this order. Stay tunned ...
Nicolas Dufresne
Comment 8 2010-11-09 14:21:29 PST
Created attachment 73415 [details] [PATCH 1/4] Allow creating hidden window Allow creating hidden window that can be destroyed if it's creation was refused by NewWindowPolicy. This is required to fullfill the synchronous requirement of JS call to window.open().
Nicolas Dufresne
Comment 9 2010-11-09 14:22:05 PST
Created attachment 73416 [details] [PATCH 2/4] Show window only after initial location request To fix this bug we enabled creating hidden windows. This patch takes benifit of this new feature and queue location change before calling Page::chrome()->show(). This mean URI can be considered sooner by non-destructive popup blocker like the one in Chrome.
Nicolas Dufresne
Comment 10 2010-11-09 14:22:40 PST
Created attachment 73417 [details] [PATCH 3/4] Don't duplicate code from FrameTree::find() In JSDOMWindow::open() we duplicate some of the code from FrameTree::find(). This patch also removes one call to FrameTree::find(). This code cleanup is attached to this bug since it ensure that createWindow is actually called to create new window, reducing side effect risk.
Nicolas Dufresne
Comment 11 2010-11-09 14:23:12 PST
Created attachment 73418 [details] [PATCH 4/4] Trigger newWindowDelegate when window.open() is called This is a bit tricky since newWindowDelegate() is normally triggered before creating the actual window. But since window.open() returns a window, we have no choice but to create it. In this patch, we play with the window visibility, creating the window and launching the newWindowDelegate() through changeLocation() and a special optional parameter. The result is that the window will only be showed if the policy is accepted, and will be closed
Nicolas Dufresne
Comment 12 2010-11-09 14:27:10 PST
Comment on attachment 73418 [details] [PATCH 4/4] Trigger newWindowDelegate when window.open() is called Note: style check fails because this patch depends on cleanup patch to apply cleanly.
Early Warning System Bot
Comment 13 2010-11-09 14:52:50 PST
WebKit Review Bot
Comment 14 2010-11-09 15:45:48 PST
Build Bot
Comment 15 2010-11-09 19:29:25 PST
Nicolas Dufresne
Comment 16 2010-11-09 19:57:18 PST
Ok, tell me what is the procedure here, because what the automated build does wont work, you can't try all patches separately, e.g. 2 depends on 1, and 4 depends on 3 and 1. Maybe I should have requested review for 1 and 3 first, and waited for them to be upstream ? thanks, and sorry for noise.
Adam Barth
Comment 17 2010-11-10 10:30:30 PST
> Ok, tell me what is the procedure here, because what the automated build does wont work, you can't try all patches separately, e.g. 2 depends on 1, and 4 depends on 3 and 1. Maybe I should have requested review for 1 and 3 first, and waited for them to be upstream ? The EWS doesn't handle dependent patch sequences. You're welcome to add support for them if you like, but it doesn't come up that often. Sorry for the bugmail spam.
WebKit Review Bot
Comment 18 2010-11-10 11:58:27 PST
Nicolas Dufresne
Comment 19 2010-11-11 11:29:38 PST
Comment on attachment 73418 [details] [PATCH 4/4] Trigger newWindowDelegate when window.open() is called It's too soon to request review, need to wait for patch 1 and 3.
Nicolas Dufresne
Comment 20 2010-11-11 11:30:11 PST
Comment on attachment 73416 [details] [PATCH 2/4] Show window only after initial location request Too soon to request view, need to wait for patch 1.
Nicolas Dufresne
Comment 21 2010-11-29 22:32:42 PST
WebKit Review Bot
Comment 22 2010-11-29 23:22:26 PST
Nicolas Dufresne
Comment 23 2010-11-30 07:57:19 PST
(In reply to comment #22) > Attachment 75107 [details] did not build on chromium: > Build output: http://queues.webkit.org/results/6459013 It seems that I broke V8 build, I'll fix soon, see log: In file included from WebCore/bindings/v8/specialization/V8BindingDOMWindow.h:34, from WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp:53: WebCore/bindings/generic/BindingDOMWindow.h: In static member function ‘static WebCore::Frame* WebCore::BindingDOMWindow<Binding>::createWindow(WebCore::State<Binding>*, WebCore::Frame*, WebCore::Frame*, WebCore::Frame*, const WTF::String&, const WTF::String&, const WebCore::WindowFeatures&, typename Binding::Value)’: WebCore/bindings/generic/BindingDOMWindow.h:128: error: ‘create’ was not declared in this scope
Adam Barth
Comment 24 2011-04-26 15:26:11 PDT
Comment on attachment 75107 [details] Patch This patch has an incorrect ChangeLog, does not contain tests, and does not compile.
Nicolas Dufresne
Comment 25 2011-04-27 08:00:48 PDT
(In reply to comment #24) > (From update of attachment 75107 [details]) > This patch has an incorrect ChangeLog Please specify so I can fix. > does not contain tests, As explain in the log, this is not visible from HTML side. As every port wraps this differently, I cannot come up with a test that works for all ports, at best I can provide a GTK port, base on the test case originally attached. > and does not compile. This can be fixed, please leave the bug open, I need to rebase against the new folder organization, and I'm doing that on free time, I have no more particular interest on my side anymore, aside correctness. If anyone needs it sooner, well take over the patch, the implementation is correct.
Martin Robinson
Comment 26 2014-04-08 18:32:27 PDT
*** Bug 34715 has been marked as a duplicate of this bug. ***
Note You need to log in before you can comment on or make changes to this bug.