diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index 123c3898a..7ed42ecff 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, 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 # 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, message, targetOrigin) -> + return unless BrowserWindow.windows.has guestId + window = BrowserWindow.windows.get(guestId) + 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 BrowserWindow.windows.get(guestId).webContents?[method] args... diff --git a/atom/renderer/lib/override.coffee b/atom/renderer/lib/override.coffee index c61cce889..e6a53399b 100644 --- a/atom/renderer/lib/override.coffee +++ b/atom/renderer/lib/override.coffee @@ -5,6 +5,9 @@ remote = require 'remote' # Window object returned by "window.open". class FakeWindow constructor: (@guestId) -> + 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 @@ -15,6 +18,9 @@ class FakeWindow blur: -> ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', @guestId, 'blur' + 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... @@ -67,3 +73,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: (message, targetOrigin) -> + ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', message, targetOrigin + +ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (message, targetOrigin) -> + window.postMessage(message, targetOrigin) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 74452282c..d3ac51f44 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](#handling-child-windows) 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.