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/api/lib/web-contents.coffee',
|
||||||
'atom/browser/lib/chrome-extension.coffee',
|
'atom/browser/lib/chrome-extension.coffee',
|
||||||
'atom/browser/lib/guest-view-manager.coffee',
|
'atom/browser/lib/guest-view-manager.coffee',
|
||||||
|
'atom/browser/lib/guest-window-manager.coffee',
|
||||||
'atom/browser/lib/init.coffee',
|
'atom/browser/lib/init.coffee',
|
||||||
'atom/browser/lib/objects-registry.coffee',
|
'atom/browser/lib/objects-registry.coffee',
|
||||||
'atom/browser/lib/rpc-server.coffee',
|
'atom/browser/lib/rpc-server.coffee',
|
||||||
|
|
|
@ -441,6 +441,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||||
.SetMethod("_send", &WebContents::SendIPCMessage)
|
.SetMethod("_send", &WebContents::SendIPCMessage)
|
||||||
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
|
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
|
||||||
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
|
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
|
||||||
|
.SetMethod("isGuest", &WebContents::is_guest)
|
||||||
.Build());
|
.Build());
|
||||||
|
|
||||||
return mate::ObjectTemplateBuilder(
|
return mate::ObjectTemplateBuilder(
|
||||||
|
|
|
@ -2,10 +2,6 @@ EventEmitter = require('events').EventEmitter
|
||||||
binding = process.atomBinding 'web_contents'
|
binding = process.atomBinding 'web_contents'
|
||||||
ipc = require 'ipc'
|
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) ->
|
module.exports.wrap = (webContents) ->
|
||||||
return null unless webContents.isAlive()
|
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'
|
process.emit 'exit'
|
||||||
|
|
||||||
# Load the RPC server.
|
# Load the RPC server.
|
||||||
require './rpc-server.js'
|
require './rpc-server'
|
||||||
|
|
||||||
# Load the guest view manager.
|
# 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.
|
# Now we try to load app's package.json.
|
||||||
packageJson = null
|
packageJson = null
|
||||||
|
|
|
@ -2,6 +2,13 @@ process = global.process
|
||||||
ipc = require 'ipc'
|
ipc = require 'ipc'
|
||||||
remote = require 'remote'
|
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?
|
unless process.guestInstanceId?
|
||||||
# Override default window.close.
|
# Override default window.close.
|
||||||
window.close = ->
|
window.close = ->
|
||||||
|
@ -25,7 +32,8 @@ window.open = (url, frameName='', features='') ->
|
||||||
options.width ?= 800
|
options.width ?= 800
|
||||||
options.height ?= 600
|
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().
|
# Use the dialog API to implement alert().
|
||||||
window.alert = (message, title='') ->
|
window.alert = (message, title='') ->
|
||||||
|
|
|
@ -32,10 +32,10 @@ describe 'chromium feature', ->
|
||||||
assert.notEqual navigator.language, ''
|
assert.notEqual navigator.language, ''
|
||||||
|
|
||||||
describe 'window.open', ->
|
describe 'window.open', ->
|
||||||
it 'returns a BrowserWindow object', ->
|
it 'returns a FakeWindow object', ->
|
||||||
b = window.open 'about:blank', 'test', 'show=no'
|
b = window.open 'about:blank', 'test', 'show=no'
|
||||||
assert.equal b.constructor.name, 'BrowserWindow'
|
assert.equal b.constructor.name, 'FakeWindow'
|
||||||
b.destroy()
|
b.close()
|
||||||
|
|
||||||
describe 'creating a Uint8Array under browser side', ->
|
describe 'creating a Uint8Array under browser side', ->
|
||||||
it 'does not crash', ->
|
it 'does not crash', ->
|
||||||
|
|
Loading…
Add table
Reference in a new issue