Use GuestWindowManager to mange windows created by window.open
This commit is contained in:
parent
9c92f2e692
commit
6f41598962
7 changed files with 77 additions and 10 deletions
1
atom.gyp
1
atom.gyp
|
@ -30,6 +30,7 @@
|
|||
'atom/browser/api/lib/web-contents.coffee',
|
||||
'atom/browser/lib/chrome-extension.coffee',
|
||||
'atom/browser/lib/guest-view-manager.coffee',
|
||||
'atom/browser/lib/guest-window-manager.coffee',
|
||||
'atom/browser/lib/init.coffee',
|
||||
'atom/browser/lib/objects-registry.coffee',
|
||||
'atom/browser/lib/rpc-server.coffee',
|
||||
|
|
|
@ -441,6 +441,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
|||
.SetMethod("_send", &WebContents::SendIPCMessage)
|
||||
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
|
||||
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
|
||||
.SetMethod("isGuest", &WebContents::is_guest)
|
||||
.Build());
|
||||
|
||||
return mate::ObjectTemplateBuilder(
|
||||
|
|
|
@ -2,10 +2,6 @@ EventEmitter = require('events').EventEmitter
|
|||
binding = process.atomBinding 'web_contents'
|
||||
ipc = require 'ipc'
|
||||
|
||||
# Routed window.open messages.
|
||||
ipc.on 'ATOM_SHELL_WEB_CONTENTS_WINDOW_OPEN', (event, args...) ->
|
||||
event.sender.emit 'new-window', event, args...
|
||||
|
||||
module.exports.wrap = (webContents) ->
|
||||
return null unless webContents.isAlive()
|
||||
|
||||
|
|
60
atom/browser/lib/guest-window-manager.coffee
Normal file
60
atom/browser/lib/guest-window-manager.coffee
Normal file
|
@ -0,0 +1,60 @@
|
|||
ipc = require 'ipc'
|
||||
v8Util = process.atomBinding 'v8_util'
|
||||
BrowserWindow = require 'browser-window'
|
||||
|
||||
guestWindows = new WeakMap
|
||||
|
||||
# Callback that registered to "closed" event of guest.
|
||||
guestUserCloseCallback = ->
|
||||
embedderId = v8Util.getHiddenValue this, 'embedderId'
|
||||
removeGuest embedderId, @id
|
||||
|
||||
# Get all guests created in a window.
|
||||
getGuestsFromEmbedder = (embedderWindow) ->
|
||||
unless guestWindows.has embedderWindow
|
||||
guests = []
|
||||
guestWindows.set embedderWindow, guests
|
||||
# Close all guests when window is closed.
|
||||
embedderWindow.on 'closed', ->
|
||||
for guest in guests
|
||||
# Avoid double removing window from guests.
|
||||
guest.removeListener 'closed', guestUserCloseCallback
|
||||
# Just close without emitting "beforeunload" event.
|
||||
guest.destroy()
|
||||
guestWindows.get embedderWindow
|
||||
|
||||
# Remove a guest window.
|
||||
removeGuest = (embedderId, guestId) ->
|
||||
guests = getGuestsFromEmbedder BrowserWindow.windows.get(embedderId)
|
||||
for guest, i in guests
|
||||
if guest.id == guestId
|
||||
guests.splice i, 1
|
||||
return guest
|
||||
|
||||
# Create a new guest created by |embedder| with |options|.
|
||||
createGuest = (embedder, url, options) ->
|
||||
embedderWindow = BrowserWindow.fromWebContents embedder
|
||||
guests = getGuestsFromEmbedder embedderWindow
|
||||
|
||||
guest = new BrowserWindow(options)
|
||||
guest.loadUrl url
|
||||
|
||||
# Remove self from guest list when user closes guest window.
|
||||
v8Util.setHiddenValue guest, 'embedderId', embedderWindow.id
|
||||
guest.on 'closed', guestUserCloseCallback
|
||||
|
||||
guests.push guest
|
||||
[embedderWindow.id, guest.id]
|
||||
|
||||
# Routed window.open messages.
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, args...) ->
|
||||
event.sender.emit 'new-window', event, args...
|
||||
if event.sender.isGuest() or event.defaultPrevented
|
||||
event.returnValue = null
|
||||
else
|
||||
[url, frameName, options] = args
|
||||
event.returnValue = createGuest event.sender, url, options
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', (event, args...) ->
|
||||
guest = removeGuest args...
|
||||
guest.destroy()
|
|
@ -58,10 +58,11 @@ process.once 'BIND_DONE', ->
|
|||
process.emit 'exit'
|
||||
|
||||
# Load the RPC server.
|
||||
require './rpc-server.js'
|
||||
require './rpc-server'
|
||||
|
||||
# Load the guest view manager.
|
||||
require './guest-view-manager.js'
|
||||
require './guest-view-manager'
|
||||
require './guest-window-manager'
|
||||
|
||||
# Now we try to load app's package.json.
|
||||
packageJson = null
|
||||
|
|
|
@ -2,6 +2,13 @@ process = global.process
|
|||
ipc = require 'ipc'
|
||||
remote = require 'remote'
|
||||
|
||||
# Window object returned by "window.open".
|
||||
class FakeWindow
|
||||
constructor: (@embedderId, @guestId) ->
|
||||
|
||||
close: ->
|
||||
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', @embedderId, @guestId
|
||||
|
||||
unless process.guestInstanceId?
|
||||
# Override default window.close.
|
||||
window.close = ->
|
||||
|
@ -25,7 +32,8 @@ window.open = (url, frameName='', features='') ->
|
|||
options.width ?= 800
|
||||
options.height ?= 600
|
||||
|
||||
ipc.send 'ATOM_SHELL_WEB_CONTENTS_WINDOW_OPEN', url, frameName, options
|
||||
[embedderId, guestId] = ipc.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, frameName, options
|
||||
new FakeWindow(embedderId, guestId)
|
||||
|
||||
# Use the dialog API to implement alert().
|
||||
window.alert = (message, title='') ->
|
||||
|
|
|
@ -32,10 +32,10 @@ describe 'chromium feature', ->
|
|||
assert.notEqual navigator.language, ''
|
||||
|
||||
describe 'window.open', ->
|
||||
it 'returns a BrowserWindow object', ->
|
||||
it 'returns a FakeWindow object', ->
|
||||
b = window.open 'about:blank', 'test', 'show=no'
|
||||
assert.equal b.constructor.name, 'BrowserWindow'
|
||||
b.destroy()
|
||||
assert.equal b.constructor.name, 'FakeWindow'
|
||||
b.close()
|
||||
|
||||
describe 'creating a Uint8Array under browser side', ->
|
||||
it 'does not crash', ->
|
||||
|
|
Loading…
Add table
Reference in a new issue