From 7fa1296a172477e11581b60ab5f78aa5188726f7 Mon Sep 17 00:00:00 2001 From: Bundyo Date: Fri, 13 Feb 2015 18:45:12 +0200 Subject: [PATCH 1/5] Implement FakeWindow.postMessage, window.opener.postMessage and window.closed flag for popup windows. --- atom/browser/lib/guest-window-manager.coffee | 12 ++++++++++++ atom/renderer/lib/override.coffee | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index 123c3898a..5ff59f5ad 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -17,9 +17,11 @@ createGuest = (embedder, url, frameName, options) -> # guest is closed by user then we should prevent |embedder| from double # closing guest. closedByEmbedder = -> + embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', guest.id guest.removeListener 'closed', closedByUser guest.destroy() unless guest.isClosed() closedByUser = -> + embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', guest.id embedder.removeListener 'render-view-deleted', closedByEmbedder embedder.once 'render-view-deleted', closedByEmbedder guest.once 'closed', closedByUser @@ -30,6 +32,10 @@ createGuest = (embedder, url, frameName, options) -> guest.once 'closed', -> delete frameToGuest[frameName] + ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, method, args...) -> + if embedder.getUrl().indexOf(args[1]) is 0 or args[1] is '*' + embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', args[0], args[1]; + guest.id # Routed window.open messages. @@ -49,6 +55,12 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method, return unless BrowserWindow.windows.has guestId BrowserWindow.windows.get(guestId)[method] args... +ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, method, args...) -> + return unless BrowserWindow.windows.has guestId + window = BrowserWindow.windows.get(guestId) + if window.getUrl().indexOf(args[1]) is 0 or args[1] is '*' + window.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', args[0], args[1] + ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) -> return unless BrowserWindow.windows.has guestId BrowserWindow.windows.get(guestId).webContents?[method] args... diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index 43ae271fb..e158497e6 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -5,6 +5,11 @@ remote = require 'remote' # Window object returned by "window.open". class FakeWindow constructor: (@guestId) -> + that = this + + ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (guestId) -> + if guestId is that.guestId + that.closed = true close: -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', @guestId @@ -15,6 +20,9 @@ class FakeWindow blur: -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', @guestId, 'blur' + postMessage: (args...) -> + ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', @guestId, 'postMessage', args[0], args[1]; + eval: (args...) -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', @guestId, 'executeJavaScript', args... @@ -63,3 +71,10 @@ window.confirm = (message, title='') -> # But we do not support prompt(). window.prompt = -> throw new Error('prompt() is and will not be supported in atom-shell.') + +window.opener = + postMessage: (args...) -> + ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', 'postMessage', args[0], args[1] + +ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (data, origin) -> + window.postMessage(data, origin) From 4e82f4c6728824206bb72f0ed6a6941638b1506d Mon Sep 17 00:00:00 2001 From: Bundyo Date: Fri, 13 Feb 2015 18:54:18 +0200 Subject: [PATCH 2/5] Remove two semicolons. --- atom/browser/lib/guest-window-manager.coffee | 2 +- atom/renderer/lib/override.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index 5ff59f5ad..3b331260b 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -34,7 +34,7 @@ createGuest = (embedder, url, frameName, options) -> ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, method, args...) -> if embedder.getUrl().indexOf(args[1]) is 0 or args[1] is '*' - embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', args[0], args[1]; + embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', args[0], args[1] guest.id diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index e158497e6..eba0e9c98 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -21,7 +21,7 @@ class FakeWindow ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', @guestId, 'blur' postMessage: (args...) -> - ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', @guestId, 'postMessage', args[0], args[1]; + ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', @guestId, 'postMessage', args[0], args[1] eval: (args...) -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', @guestId, 'executeJavaScript', args... From c7562dbfd0fb91e88f7d08a3841f325fd5332345 Mon Sep 17 00:00:00 2001 From: bundyo Date: Sat, 28 Feb 2015 10:31:07 +0200 Subject: [PATCH 3/5] Add FakeWindow documentation. --- docs/api/browser-window.md | 53 +++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 74452282c..1defec2ac 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -641,9 +641,7 @@ Emitted when a redirect was received while requesting a resource. Emitted when the page requested to open a new window for `url`. It could be requested by `window.open` or an external link like ``. - -By default a new `BrowserWindow` will be created for the `url`, and a proxy -will be returned to `window.open` to let you have limited control of it. +Check the next section [Handling Child Windows](#handlingchildwindows) for more information. Calling `event.preventDefault()` can prevent creating new windows. @@ -844,3 +842,52 @@ app.on('ready', function() { is different from the handlers on browser side. 2. There is no way to send synchronous messages from browser side to web pages, because it would be very easy to cause dead locks. + +## Handling Child Windows + +When the page contents request opening a new window, either by invoking +`window.open` or by an external link such as ``, by +default a new `BrowserWindow` will be created for the `url`, and a proxy +will be returned to `window.open` to let the page to have limited control over it. + +The proxy has some limited standard functionality implemented, which will help +the page to interact with it. The following methods are avaialable: + +### Window.blur() + +Removes focus from the child window. + +### Window.close() + +Forcefully closes the child window without calling its unload event. + +### Window.closed + +Set to true after the child window gets closed. + +### Window.eval(code) + +* `code` String + +Evaluates the code in the child window. + +### Window.focus() + +Focuses the child window (brings the window to front). + +### Window.postMessage(message, targetOrigin) + +* `message` String +* `targetOrigin` String + +Sends a message to the child window with the specified origin or "*" for no origin preference. + +In addition to these methods, the child window implements `window.opener` object with no properties +and a single method: + +### window.opener.postMessage(message, targetOrigin) + +* `message` String +* `targetOrigin` String + +Sends a message to the parent window with the specified origin or "*" for no origin preference. From e8d648bcba4d84cc9a267bf3064757857a695d43 Mon Sep 17 00:00:00 2001 From: bundyo Date: Sat, 28 Feb 2015 10:34:26 +0200 Subject: [PATCH 4/5] Change the link to use dashes. --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 1defec2ac..d3ac51f44 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -641,7 +641,7 @@ Emitted when a redirect was received while requesting a resource. Emitted when the page requested to open a new window for `url`. It could be requested by `window.open` or an external link like ``. -Check the next section [Handling Child Windows](#handlingchildwindows) for more information. +Check the next section [Handling Child Windows](#handling-child-windows) for more information. Calling `event.preventDefault()` can prevent creating new windows. From dbbc35bd1305ca82fa9fe0417b2c37b43bec6205 Mon Sep 17 00:00:00 2001 From: Bundyo Date: Wed, 4 Mar 2015 11:29:52 +0200 Subject: [PATCH 5/5] Fixes after code review. --- atom/browser/lib/guest-window-manager.coffee | 12 ++++++------ atom/renderer/lib/override.coffee | 20 +++++++++----------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index 3b331260b..7ed42ecff 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -32,9 +32,9 @@ createGuest = (embedder, url, frameName, options) -> guest.once 'closed', -> delete frameToGuest[frameName] - ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, method, args...) -> - if embedder.getUrl().indexOf(args[1]) is 0 or args[1] is '*' - embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', args[0], args[1] + ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, message, targetOrigin) -> + if embedder.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*' + embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', message, targetOrigin guest.id @@ -55,11 +55,11 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method, return unless BrowserWindow.windows.has guestId BrowserWindow.windows.get(guestId)[method] args... -ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, method, args...) -> +ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, message, targetOrigin) -> return unless BrowserWindow.windows.has guestId window = BrowserWindow.windows.get(guestId) - if window.getUrl().indexOf(args[1]) is 0 or args[1] is '*' - window.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', args[0], args[1] + if window.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*' + window.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', message, targetOrigin ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) -> return unless BrowserWindow.windows.has guestId diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index eba0e9c98..a727da59c 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -5,11 +5,9 @@ remote = require 'remote' # Window object returned by "window.open". class FakeWindow constructor: (@guestId) -> - that = this - - ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (guestId) -> - if guestId is that.guestId - that.closed = true + ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (guestId) => + if guestId is @guestId + @closed = true close: -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', @guestId @@ -20,8 +18,8 @@ class FakeWindow blur: -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', @guestId, 'blur' - postMessage: (args...) -> - ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', @guestId, 'postMessage', args[0], args[1] + postMessage: (message, targetOrigin) -> + ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', @guestId, message, targetOrigin eval: (args...) -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', @guestId, 'executeJavaScript', args... @@ -73,8 +71,8 @@ window.prompt = -> throw new Error('prompt() is and will not be supported in atom-shell.') window.opener = - postMessage: (args...) -> - ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', 'postMessage', args[0], args[1] + postMessage: (message, targetOrigin) -> + ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', message, targetOrigin -ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (data, origin) -> - window.postMessage(data, origin) +ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (message, targetOrigin) -> + window.postMessage(message, targetOrigin)