mirror of
https://github.com/mistergibson/gxg-web-client.git
synced 2026-08-15 11:34:29 -07:00
741 lines
36 KiB
Ruby
741 lines
36 KiB
Ruby
#
|
|
#require 'gxg_uri'
|
|
#
|
|
module GxG
|
|
module Networking
|
|
class Channel
|
|
#
|
|
end
|
|
#
|
|
class Connector
|
|
#
|
|
def remote_uuid()
|
|
@remote_uuid
|
|
end
|
|
#
|
|
def open?()
|
|
@active
|
|
end
|
|
#
|
|
def close()
|
|
the_message = new_message({:operation => "close", :display_path => @display_path})
|
|
the_message[:sender] = @uuid
|
|
the_message[:to] = @remote_uuid
|
|
self.pull(the_message,{:synchronous => true})
|
|
@active = false
|
|
@csrf = nil
|
|
if @heart_beat_timer.is_a?(::Hash)
|
|
GxG::DISPATCHER.cancel_timer(@heart_beat_timer)
|
|
end
|
|
end
|
|
#
|
|
def push(the_message=nil,options={})
|
|
if @active
|
|
# Uses PUT method, with data payload
|
|
if the_message.is_a?(::GxG::Events::Message)
|
|
payload = the_message.body.to_json.to_s
|
|
the_xhr = `new XMLHttpRequest`
|
|
`#{the_xhr}.open('PUT',#{@host_prefix},true)`
|
|
`#{the_xhr}.timeout = #{(options[:timeout] || 5000)}`
|
|
`#{the_xhr}.setRequestHeader('X-Requested-With','XMLHttpRequest')`
|
|
`#{the_xhr}.setRequestHeader('Accept','application/json')`
|
|
`#{the_xhr}.setRequestHeader('X-CSRF-Token', #{@csrf})`
|
|
`#{the_xhr}.setRequestHeader('Content-Type', 'application/json')`
|
|
# unless (`navigator.userAgent`).include?("Firefox") || (`navigator.userAgent`).include?("Chrome")
|
|
# `#{the_xhr}.setRequestHeader('Content-Length', #{payload.size})`
|
|
# end
|
|
failed = Proc.new do |reason=nil|
|
|
the_message.fail(reason)
|
|
end
|
|
succeeded = Proc.new do
|
|
response_code = (`#{the_xhr}.status`).to_i
|
|
if response_code < 300
|
|
the_message.succeed(::JSON.parse(`#{the_xhr}.response`,{:symbolize_names => true}))
|
|
else
|
|
failed.call(response_code)
|
|
end
|
|
end
|
|
`#{the_xhr}.addEventListener('load', #{succeeded})`
|
|
`#{the_xhr}.addEventListener('error', #{failed})`
|
|
`#{the_xhr}.addEventListener('timeout', #{failed})`
|
|
`#{the_xhr}.addEventListener('abort', #{failed})`
|
|
`#{the_xhr}.send(#{payload})`
|
|
#
|
|
true
|
|
else
|
|
# error?
|
|
false
|
|
end
|
|
end
|
|
#
|
|
end
|
|
#
|
|
def pull(the_message=nil,options={:synchronous => false})
|
|
if @active
|
|
# Uses GET method, with in-URL query specifiers (no data payload)
|
|
if the_message.is_a?(::GxG::Events::Message)
|
|
the_query = ""
|
|
the_message.body.keys.each do |the_key|
|
|
the_query = the_query + ("#{the_key.to_s}=#{the_message.body[(the_key)].to_s}")
|
|
unless the_key == the_message.body.keys.last
|
|
the_query = the_query + "&"
|
|
end
|
|
end
|
|
the_url = (@host_prefix.to_s + "?" + the_query)
|
|
the_xhr = `new XMLHttpRequest`
|
|
if options[:synchronous] == true
|
|
`#{the_xhr}.open('GET',#{the_url.to_s},false)`
|
|
else
|
|
`#{the_xhr}.open('GET',#{the_url.to_s},true)`
|
|
`#{the_xhr}.timeout = #{(options[:timeout] || 600000)}`
|
|
end
|
|
`#{the_xhr}.setRequestHeader('X-Requested-With','XMLHttpRequest')`
|
|
`#{the_xhr}.setRequestHeader('Accept','application/json')`
|
|
failed = Proc.new do |reason=nil|
|
|
the_message.fail(reason)
|
|
end
|
|
succeeded = Proc.new do
|
|
response_code = (`#{the_xhr}.status`).to_i
|
|
if response_code < 300
|
|
the_message.succeed(::JSON.parse(`#{the_xhr}.response`,{:symbolize_names => true}))
|
|
else
|
|
failed.call(response_code)
|
|
end
|
|
end
|
|
`#{the_xhr}.addEventListener('load', #{succeeded})`
|
|
`#{the_xhr}.addEventListener('error', #{failed})`
|
|
`#{the_xhr}.addEventListener('timeout', #{failed})`
|
|
`#{the_xhr}.addEventListener('abort', #{failed})`
|
|
`#{the_xhr}.send(null)`
|
|
#
|
|
true
|
|
else
|
|
# error?
|
|
false
|
|
end
|
|
end
|
|
#
|
|
end
|
|
#
|
|
def push_message(the_message=nil)
|
|
# TODO: establish a sensible routing scheme and make better use of message :sender and :to in that idea.
|
|
end
|
|
#
|
|
def pull_message(options={})
|
|
# Use to pull a message portion or look for application messages on the server.
|
|
end
|
|
#
|
|
def process_pending(options={})
|
|
#
|
|
end
|
|
# Support-level methods for pulling/pushing objects or object-deltas.
|
|
def push_object_portions(details={}, error_handler=nil, &the_handler)
|
|
# supply thread and index to send, if successful, will post event to keep chain going.
|
|
# Details: {:thread => "", :index => 0, :portions => 100}
|
|
end
|
|
# Search The Database(s)
|
|
def search_database(details={}, error_handler=nil, &the_handler)
|
|
# FOR NOW: limit 100 records returned at a time.
|
|
# Use: {:limit => 100, :offset => 0} || {:page => 1}
|
|
if details.is_a?(::Hash) && the_handler
|
|
self.pull_data({:operation => :search_database, :criteria => details},error_handler) do |data|
|
|
if data.is_a?(::Hash)
|
|
the_handler.call(data)
|
|
end
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
# High-level methods for pulling/pushing objects or object-deltas.
|
|
def destroy_object(the_specifier=nil,error_handler=nil,&the_handler)
|
|
if the_specifier && the_handler
|
|
self.pull_data({:operation => :destroy_object, :location => the_specifier},error_handler) do |data|
|
|
if data.is_a?(::Hash)
|
|
the_handler.call(data)
|
|
end
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
#
|
|
def push_data(details={}, error_handler=nil,&the_handler)
|
|
if details.is_a?(::Hash) && the_handler
|
|
content = details.to_json.to_s.encode64
|
|
msg_frame = {:sender => @uuid.to_s, :to => @remote_uuid.to_s, :display_path => @display_path, :operation => "put_portion", :thread => "00000000-0000-4000-0000-000000000000", :index => 99999, :total => 100000, :payload => ""}
|
|
portions = ::GxG::apportioned_ranges(content.size,(65536 - msg_frame.to_json.size))
|
|
#
|
|
if portions.size > 1
|
|
the_message = new_message({ :operation => "put_data", :display_path => @display_path})
|
|
the_message[:sender] = @uuid
|
|
the_message[:to] = @remote_uuid
|
|
the_message[:body][:thread] = the_message.id().to_s
|
|
#
|
|
if the_handler.respond_to?(:call)
|
|
the_message.on(:success) do |response|
|
|
@buffer.delete(the_message[:body][:thread])
|
|
the_handler.call(response)
|
|
end
|
|
end
|
|
if error_handler.respond_to?(:call)
|
|
the_message.on(:fail) do |response|
|
|
@buffer.delete(the_message[:body][:thread])
|
|
error_handler.call(response)
|
|
end
|
|
end
|
|
#
|
|
@buffer[(the_message[:body][:thread])] = []
|
|
#
|
|
portions.each_with_index do |the_range, indexer|
|
|
the_msg_portion = msg_frame.clone
|
|
the_msg_portion[:thread] = the_message[:body][:thread]
|
|
the_msg_portion[:index] = indexer
|
|
the_msg_portion[:total] = portions.size
|
|
the_msg_portion[:payload] = content[(the_range)]
|
|
@buffer[(the_message[:body][:thread])] << the_msg_portion
|
|
end
|
|
# -----------------------------------------------------
|
|
# Send portions
|
|
(0..(portions.size - 1)).each do |the_portion|
|
|
::GxG::DISPATCHER.post_event(:communications) do
|
|
if @buffer[(the_message[:body][:thread])].is_a?(::Array)
|
|
if @buffer[(the_message[:body][:thread])][(the_portion)].is_a?(::Hash)
|
|
#
|
|
portion_message = new_message(@buffer[(the_message[:body][:thread])][(the_portion)])
|
|
portion_message[:sender] = @uuid
|
|
portion_message[:to] = @remote_uuid
|
|
#
|
|
portion_message.on(:succeed) do |response|
|
|
if the_portion == (@buffer[(the_message[:body][:thread])].size - 1)
|
|
if @buffer[(the_message[:body][:thread])]
|
|
GxG::CONNECTION.push(the_message)
|
|
end
|
|
end
|
|
end
|
|
#
|
|
portion_message.on(:fail) do |response|
|
|
the_message.fail(response)
|
|
end
|
|
#
|
|
GxG::CONNECTION.push(portion_message)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
#
|
|
else
|
|
# single message payload
|
|
the_message = new_message({ :operation => "put_data", :display_path => @display_path, :payload => content})
|
|
the_message[:sender] = @uuid
|
|
the_message[:to] = @remote_uuid
|
|
GxG::CONNECTION.push(the_message)
|
|
end
|
|
#
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
#
|
|
def push_object(details={}, error_handler=nil,&the_handler)
|
|
if details.is_a?(::Hash) && the_handler
|
|
self.push_data({:operation => :put_object, :data => details},error_handler) do |data|
|
|
if data.is_a?(::Hash)
|
|
the_handler.call(data)
|
|
end
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
#
|
|
def pull_data(the_specifier={},error_handler=nil,&the_handler)
|
|
if the_specifier && the_handler
|
|
the_message = new_message({:operation => "get_data", :thread => nil, :display_path => @display_path, :details => the_specifier.to_json.encode64})
|
|
the_message[:sender] = @uuid
|
|
the_message[:to] = @remote_uuid
|
|
the_message[:body][:thread] = the_message.id().to_s
|
|
if error_handler.respond_to?(:call)
|
|
the_message.on(:fail,&error_handler)
|
|
end
|
|
the_message.on(:success) do |response|
|
|
if response.is_a?(::Hash)
|
|
if response[:result] == true
|
|
case response[:operation]
|
|
when "this_portion"
|
|
data = response[:payload]
|
|
if data.is_a?(::String)
|
|
# FIXME: <String>.base64? needs a proper working regex (or go brute force)
|
|
# data = Base64::strict_decode64(data)
|
|
if data.base64?
|
|
data = data.decode64
|
|
end
|
|
if data.json?
|
|
begin
|
|
data = ::JSON::parse(data,{:symbolize_names => true})
|
|
rescue Exception => the_error
|
|
log_error({:error => the_error, :parameters => {:data => data}})
|
|
end
|
|
end
|
|
the_handler.call(data)
|
|
else
|
|
log_error({:error => Exception.new("Malformed Response Data"), :parameters => {:data => data}})
|
|
end
|
|
when "get_portions"
|
|
@pending[(response[:thread])] = the_message
|
|
@buffers[(response[:thread])] = []
|
|
the_messages = []
|
|
(0..(response[:total] - 1)).each do |indexer|
|
|
portion_message = new_message({:operation => "get_portion", :thread => (response[:thread]), :index => indexer, :display_path => @display_path})
|
|
portion_message[:sender] = @uuid
|
|
portion_message[:to] = @remote_uuid
|
|
#
|
|
portion_message.on(:success) do |reply|
|
|
@buffers[(response[:thread])] << reply
|
|
if @buffers[(response[:thread])].size == response[:total]
|
|
already = []
|
|
the_data = ""
|
|
until already.size == response[:total] do
|
|
(0..(response[:total] - 1)).each do |referencer|
|
|
unless already.index(referencer)
|
|
the_data = (the_data + (@buffers[(response[:thread])][(referencer)][:payload]))
|
|
already << referencer
|
|
break
|
|
end
|
|
end
|
|
end
|
|
signal_message = new_message({:operation => "got_portions", :thread => response[:thread], :display_path => @display_path})
|
|
signal_message[:sender] = @uuid
|
|
signal_message[:to] = @remote_uuid
|
|
GxG::CONNECTION.pull(signal_message)
|
|
#
|
|
@pending.delete(response[:thread])
|
|
@buffers.delete(response[:thread])
|
|
if the_data.size > 0
|
|
# FIXME: <String>.base64? needs a proper working regex (or go brute force)
|
|
# the_data = Base64::strict_decode64(the_data)
|
|
if the_data.base64?
|
|
the_data = the_data.decode64
|
|
end
|
|
if the_data.json?
|
|
begin
|
|
the_data = ::JSON::parse(the_data,{:symbolize_names => true})
|
|
rescue Exception => the_error
|
|
log_error({:error => the_error, :parameters => {:data => the_data}})
|
|
end
|
|
end
|
|
the_handler.call(the_data)
|
|
else
|
|
log_warn("Empty payload from portions.")
|
|
end
|
|
end
|
|
end
|
|
#
|
|
portion_message.on(:fail) do |reply|
|
|
log_warn("Cancelling Transfer: portion #{indexer} of thread #{response[:thread]}.")
|
|
@pending.delete(response[:thread])
|
|
@buffers.delete(response[:thread])
|
|
if error_handler.respond_to?(:call)
|
|
error_handler.call(reply)
|
|
end
|
|
end
|
|
#
|
|
# GxG::CONNECTION.pull(portion_message)
|
|
the_messages << portion_message
|
|
#
|
|
end
|
|
the_messages.each do |a_message|
|
|
GxG::CONNECTION.pull(a_message)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
GxG::CONNECTION.pull(the_message)
|
|
end
|
|
end
|
|
#
|
|
def pull_object(the_specifier=nil,error_handler=nil,&the_handler)
|
|
# Use pull_data({:operation => :get_object, :location => the_specifier})
|
|
if the_specifier && the_handler
|
|
# GxG::DISPLAY_DETAILS[:object].set_busy(true)
|
|
self.pull_data({:operation => :get_object, :location => the_specifier},error_handler) do |data|
|
|
if data.is_a?(::Hash)
|
|
the_handler.call(::GxG::Database::process_detached_import(data))
|
|
# GxG::DISPLAY_DETAILS[:object].set_busy(false)
|
|
end
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
#
|
|
def get_permissions(the_specifier=nil,error_handler=nil,&the_handler)
|
|
# See vfs: :action => 'set_permissions', :path => (location), :alterations => [{:credential => nil, :permissions => {...}}], :revocations => [(a-credential)]
|
|
if the_specifier && the_handler
|
|
# GxG::DISPLAY_DETAILS[:object].set_busy(true)
|
|
self.pull_data({:operation => :get_permissions, :location => the_specifier},error_handler) do |data|
|
|
if data.is_a?(::Hash)
|
|
the_handler.call(data)
|
|
# GxG::DISPLAY_DETAILS[:object].set_busy(false)
|
|
end
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
#
|
|
# Libarary Loading Support:
|
|
def library_pull(details={}, error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if details.is_a?(::Hash) && the_handler
|
|
self.pull_data({:operation => :get_library}.merge!(details),error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
# Format Support:
|
|
def format_pull(details={}, error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if details.is_any?(::Array, ::Hash) && the_handler
|
|
self.pull_data({:operation => :format_pull, :criteria => details},error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
# TODO: format_push(data={})
|
|
# Admin:
|
|
def admin(details={}, error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if details.is_a?(::Hash) && the_handler
|
|
self.pull_data(({:operation => :admin}.merge!(details)),error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
#
|
|
# VFS:
|
|
def vfs(details={}, error_handler=nil, &the_handler)
|
|
# Specify either a :location or :name
|
|
if self.open?
|
|
if details.is_a?(::Hash) && the_handler
|
|
self.pull_data(({:operation => :vfs}.merge!(details)),error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
#
|
|
# Application Support:
|
|
def app_state_push(details={}, error_handler=nil, &the_handler)
|
|
if details.is_a?(::Hash) && the_handler
|
|
self.push_data({:operation => :app_state_push, :application => details[:application], :data => details[:data]},error_handler) do |data|
|
|
if data.is_a?(::Hash)
|
|
the_handler.call(data)
|
|
end
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
#
|
|
def app_state_pull(details={}, error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if details.is_a?(::Hash) && the_handler
|
|
self.pull_data({:operation => :app_state_pull, :application => details[:application]},error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
#
|
|
def application_open(details={}, error_handler=nil, &the_handler)
|
|
# Specify either a :location or :name
|
|
if self.open?
|
|
if details.is_a?(::Hash) && the_handler
|
|
if details[:name]
|
|
self.pull_data({:operation => :application_open, :restore => (details[:restore] || false), :name => details[:name]},error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
else
|
|
self.pull_data({:operation => :application_open, :restore => (details[:restore] || false), :location => details[:location]},error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
#
|
|
def application_close(details={}, error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if details.is_a?(::Hash) && the_handler
|
|
self.pull_data({:operation => :application_close, :application => details[:application]},error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
#
|
|
def application_list(error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if the_handler
|
|
self.pull_data({:operation => :application_list},error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
#
|
|
def application_menu(error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if the_handler
|
|
self.pull_data({:operation => :application_menu},error_handler) do |data|
|
|
the_handler.call(data)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
#
|
|
def entries(details={}, error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if details.is_a?(::Hash) && the_handler
|
|
GxG::DISPLAY_DETAILS[:object].set_busy(true)
|
|
self.pull_data({:operation => :entries, :location => details[:location]},error_handler) do |data|
|
|
the_handler.call(data)
|
|
GxG::DISPLAY_DETAILS[:object].set_busy(false)
|
|
end
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
#
|
|
def heartbeat()
|
|
if @active
|
|
heartbeat_message = new_message({:operation => "heartbeat", :display_path => @display_path})
|
|
heartbeat_message[:sender] = @uuid.to_s
|
|
heartbeat_message[:to] = @remote_uuid.to_s
|
|
heartbeat_message.on(:success) do |response|
|
|
if response.is_a?(::Hash)
|
|
# FIXME: possible conflict with proper credential setting.
|
|
if response[:result][:status] == "credentialed"
|
|
# GxG::DISPLAY_DETAILS[:logged_in] = true
|
|
else
|
|
# GxG::DISPLAY_DETAILS[:logged_in] = false
|
|
end
|
|
GxG::DISPLAY_DETAILS[:server_status] = response[:result][:server].to_s.to_sym
|
|
end
|
|
end
|
|
GxG::CONNECTION.pull(heartbeat_message)
|
|
end
|
|
end
|
|
#
|
|
# Set Credential:
|
|
def update_credential(details={}, error_handler=nil, &the_handler)
|
|
if self.open?
|
|
if details.is_a?(::Hash) && the_handler
|
|
content = details.to_json.to_s.encrypt(@csrf.to_s).encode64
|
|
the_message = new_message({:operation => "update_credential", :display_path => @display_path, :payload => content})
|
|
the_message[:sender] = @uuid
|
|
the_message[:to] = @remote_uuid
|
|
the_message[:body][:thread] = the_message.id().to_s
|
|
the_message.on(:success) do |the_response|
|
|
if the_response.is_a?(::Hash)
|
|
if the_response[:status] == "credentialed"
|
|
GxG::DISPLAY_DETAILS[:logged_in] = true
|
|
end
|
|
end
|
|
the_handler.call(the_response)
|
|
end
|
|
if error_handler
|
|
the_message.on(:fail) do |the_response|
|
|
error_handler.call(the_response)
|
|
end
|
|
end
|
|
GxG::CONNECTION.push(the_message)
|
|
end
|
|
end
|
|
end
|
|
#
|
|
def downgrade_credential(&the_handler)
|
|
# ????
|
|
if @active
|
|
downgrade_message = new_message({:operation => "downgrade_credential", :display_path => @display_path})
|
|
downgrade_message[:sender] = @uuid.to_s
|
|
downgrade_message[:to] = @remote_uuid.to_s
|
|
downgrade_message.on(:success) do |response|
|
|
# var evt = new CustomEvent('credentialchanged', { detail: "state" }); ??
|
|
# window.dispatchEvent(evt);
|
|
if response.is_a?(::Hash)
|
|
# FIXME: possible conflict with proper credential setting.
|
|
if response[:status] == "uncredentialed"
|
|
GxG::DISPLAY_DETAILS[:logged_in] = false
|
|
if the_handler.respond_to?(:call)
|
|
the_handler.call(response)
|
|
end
|
|
new_event = `new CustomEvent('credentialchanged', { detail: #{response[:status].to_s} })`
|
|
`window.dispatchEvent(#{new_event})`
|
|
else
|
|
# GxG::DISPLAY_DETAILS[:logged_in] = true
|
|
end
|
|
# GxG::DISPLAY_DETAILS[:server_status] = response[:server].to_s.to_sym
|
|
end
|
|
end
|
|
GxG::CONNECTION.pull(downgrade_message)
|
|
end
|
|
end
|
|
#
|
|
def relative_url()
|
|
@relative_url
|
|
end
|
|
#
|
|
def query()
|
|
@query
|
|
end
|
|
#
|
|
def article()
|
|
@article
|
|
end
|
|
#
|
|
def initialize()
|
|
if (`window.location['href']`).include?("https://")
|
|
@host_prefix = ("https://" + `window.location['host']`)
|
|
else
|
|
@host_prefix = ("http://" + `window.location['host']`)
|
|
end
|
|
@relative_url = ""
|
|
# Find Relative URL
|
|
page_name = File::basename(`window.location['pathname']`)
|
|
subpath_array = (`window.location['pathname']`.split("/"))
|
|
found_at = subpath_array.index(page_name)
|
|
if found_at.is_a?(::Numeric)
|
|
if found_at > 1
|
|
@relative_url = subpath_array[(0..(found_at - 1))].join("/")
|
|
end
|
|
end
|
|
# Process Query if found
|
|
@article = nil
|
|
@query = {}
|
|
query_string = `window.location.href`.split("?")[1]
|
|
if query_string
|
|
@article = query_string.split("#")[1]
|
|
query_string = query_string.split("#")[0]
|
|
if query_string.include?("&")
|
|
query_array = query_string.split("&")
|
|
else
|
|
query_array = query_string.split("&")
|
|
end
|
|
query_array.each do |entry|
|
|
buffer = entry.split("=")
|
|
@query[(buffer[0].to_s.to_sym)] = buffer[1]
|
|
end
|
|
else
|
|
@article = `window.location.href`.split("#")[1]
|
|
end
|
|
#
|
|
@uuid = GxG.uuid_generate().to_sym
|
|
@remote_uuid = nil
|
|
@active = true
|
|
@display_path = nil
|
|
@in_busy = false
|
|
@out_busy = false
|
|
@pending = {}
|
|
@channels = {}
|
|
@buffers = {}
|
|
@csrf = nil
|
|
@the_connector = self
|
|
# Make introduction to host and aquire csrf token
|
|
the_introduction = new_message({:operation => "introduction", :introducing => @uuid.to_s})
|
|
the_introduction[:sender] = @uuid.to_s
|
|
the_introduction[:to] = @host_prefix.to_s
|
|
the_introduction.on(:success) do |response|
|
|
if response[:result] == "OK"
|
|
if response[:csrf]
|
|
@csrf = response[:csrf]
|
|
end
|
|
if response[:status] == "credentialed"
|
|
GxG::DISPLAY_DETAILS[:logged_in] = true
|
|
else
|
|
GxG::DISPLAY_DETAILS[:logged_in] = false
|
|
end
|
|
#
|
|
if response[:display] == "unavailable"
|
|
`alert('Display Resource Unavailable')`
|
|
else
|
|
@display_path = response[:display]
|
|
@active = true
|
|
# Are we logged in at the server and recovering from a crash ??
|
|
GxG::DISPATCHER.post_event(:display) do
|
|
until (`document.readyState`.to_s == "complete") do
|
|
sleep 0.5
|
|
end
|
|
::GxG::DISPLAY_DETAILS[:query] = @query
|
|
::GxG::DISPLAY_DETAILS[:article] = @article
|
|
::GxG::DISPLAY_DETAILS[:object] = ::GxG::Gui::Page.new(@display_path)
|
|
GxG::DISPATCHER.post_event(:display) do
|
|
sleep 1.0
|
|
::GxG::DISPLAY_DETAILS[:object].layout_refresh
|
|
end
|
|
end
|
|
#
|
|
end
|
|
#
|
|
end
|
|
end
|
|
the_introduction.on(:fail) do |response|
|
|
@active = false
|
|
log_error({:error => Exception.new("Communication Error"), :parameters => {:response => response}})
|
|
end
|
|
GxG::DISPATCHER.post_event(:communications) do
|
|
GxG::CONNECTION.pull(the_introduction)
|
|
@heart_beat_timer = GxG::DISPATCHER.add_periodic_timer({:interval => 60.0}) do
|
|
GxG::CONNECTION.heartbeat()
|
|
end
|
|
end
|
|
#
|
|
`window.addEventListener('unload', do_unload,false);function do_unload() { Opal.GxG.$eval("GxG::CONNECTION.close"); };`
|
|
#
|
|
self
|
|
end
|
|
#
|
|
end
|
|
end
|
|
end
|