electron/browser/atom/rpc_server.coffee
Cheng Zhao bcf6cd9f1b Drop support for cross-process callbacks.
Now it's forbidden for browser to store reference to objects (including
functions) in renderer, because when the renderer is destroyed, it's
extremely hard to clean all of corresponding objects in browser
correctly, which would cause very bad resources leak.
2013-04-30 22:37:54 +08:00

104 lines
3.6 KiB
CoffeeScript

ipc = require 'ipc'
path = require 'path'
objectsRegistry = require './objects_registry.js'
# Convert a real value into a POD structure which carries information of this
# value.
class Meta
constructor: (processId, routingId, value) ->
@type = typeof value
@type = 'value' if value is null
@type = 'array' if Array.isArray value
# Treat the arguments object as array.
@type = 'array' if @type is 'object' and value.callee? and value.length?
if @type is 'array'
@members = []
@members.push new Meta(processId, routingId, el) for el in value
else if @type is 'object' or @type is 'function'
@name = value.constructor.name
# Reference the original value if it's an object, because when it's
# passed to renderer we would assume the renderer keeps a reference of
# it.
@storeId = objectsRegistry.add processId, routingId, value
@id = value.id
@members = []
@members.push { name: prop, type: typeof field } for prop, field of value
else
@type = 'value'
@value = value
ipc.on 'ATOM_BROWSER_REQUIRE', (event, processId, routingId, module) ->
try
event.result = new Meta(processId, routingId, require(module))
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_GLOBAL', (event, processId, routingId, name) ->
try
event.result = new Meta(processId, routingId, global[name])
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event, processId, routingId) ->
try
windows = objectsRegistry.getAllWindows()
for window in windows
break if window.getProcessID() == processId and
window.getRoutingID() == routingId
event.result = new Meta(processId, routingId, window)
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_CONSTRUCTOR', (event, processId, routingId, id, args) ->
try
constructor = objectsRegistry.get id
# Call new with array of arguments.
# http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
obj = new (Function::bind.apply(constructor, [null].concat(args)))
event.result = new Meta(processId, routingId, obj)
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, processId, routingId, id, args) ->
try
func = objectsRegistry.get id
ret = func.apply global, args
event.result = new Meta(processId, routingId, ret)
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, processId, routingId, id, method, args) ->
try
obj = objectsRegistry.get id
ret = obj[method].apply(obj, args)
event.result = new Meta(processId, routingId, ret)
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, processId, routingId, id, name, value) ->
try
obj = objectsRegistry.get id
obj[name] = value
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_MEMBER_GET', (event, processId, routingId, id, name) ->
try
obj = objectsRegistry.get id
event.result = new Meta(processId, routingId, obj[name])
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_REFERENCE', (event, processId, routingId, id) ->
try
obj = objectsRegistry.get id
event.result = new Meta(processId, routingId, obj)
catch e
event.result = type: 'error', value: e.message
ipc.on 'ATOM_BROWSER_DEREFERENCE', (processId, routingId, storeId) ->
objectsRegistry.remove processId, routingId, storeId