Example #1
0
def generate_static(App, writefile):
    # prepare main_html ...
    mfn = os.path.realpath(__file__)
    mfn = os.path.dirname(mfn)

    if hasattr(App, 'main_html_file_path'):
        main_html_file_path = App.main_html_file_path
    else:
        main_html_file_path = None

    if not main_html_file_path:
        ffn = os.path.join(mfn, 'main.html')
    else:
        ffn = main_html_file_path
    lines = []
    with open(ffn, 'r') as f:
        for l in f:
            if l.strip() == '<body onload="init_communication()">':
                l = '<body>'
            if l.lstrip().startswith('-->'):
                fnjs = l.split()[1].strip()
                if fnjs in ['js/classy.js', 'js/weba.js']:
                    mfn = os.path.realpath(__file__)
                    mfn = os.path.dirname(mfn)
                    fnjs = os.path.join(mfn, fnjs)
                    with open(fnjs, 'r') as fjs:
                        l = fjs.read()
                    lines.append(l)
                    continue
                if fnjs == 'include':
                    if hasattr(App, 'include'):
                        for i in App.include:
                            lines.append('<script src="'+i+'"></script>\n')
                    continue
                if fnjs == 'meta':
                    if hasattr(App, 'meta'):
                        for m in App.meta:
                            js = '<meta '
                            for a, v in m.items():
                                js += a+'="'+v+'" '
                            js += '>\n'
                            lines.append(js)
                    continue
                if fnjs != 'websocket':
                    continue
            lines.append(l)
    main_html = ''.join(lines)

    static_html = []
    for l in lines:
        if l.lstrip().startswith('-->'):
            rdoc = RemoteDocument()
            app = App()
            app.initialize(remote_document=rdoc, main_html=main_html)
            l = rdoc.pop_all_code()
        static_html.append(l)
    static_html = ''.join(static_html)

    with open(writefile, 'w') as f:
        f.write(static_html)
Example #2
0
 def initialize(self, **kwargs):
     log.info('Initiallizing a websocket handler!')
     try:
         self.id = _generate_session_id()
         self.remotedocument = RemoteDocument()
         self.closed = True
         self.session_id = None
         self.tab_id = None
         self.vendor_type = None
         self.shared_data = kwargs['shared_data']
         self.session_data_store = kwargs['session_data_store']
         self.tab_data_store = kwargs['tab_data_store']
         self.session_data = None
         self.tab_data = None
         self.local_doc = kwargs['local_doc_class']()
         self.local_doc_initialized = False
         self.sharedhandlers = kwargs['shared_wshandlers']
         self.sharedhandlers[self.id] = self
         self.is_new_tab = None
         self.is_new_session = None
         self.main_html = kwargs['main_html']
     except:
         log.exception('Initialization of websocket handler failed!')
Example #3
0
class WebSocketHandler(webalchemy.tornado.websocket.WebSocketHandler):

    @gen.coroutine
    def initialize(self, **kwargs):
        log.info('Initiallizing a websocket handler!')
        try:
            self.id = _generate_session_id()
            self.remotedocument = RemoteDocument()
            self.closed = True
            self.session_id = None
            self.tab_id = None
            self.vendor_type = None
            self.shared_data = kwargs['shared_data']
            self.session_data_store = kwargs['session_data_store']
            self.tab_data_store = kwargs['tab_data_store']
            self.session_data = None
            self.tab_data = None
            self.local_doc = kwargs['local_doc_class']()
            self.local_doc_initialized = False
            self.sharedhandlers = kwargs['shared_wshandlers']
            self.sharedhandlers[self.id] = self
            self.is_new_tab = None
            self.is_new_session = None
            self.main_html = kwargs['main_html']
        except:
            log.exception('Initialization of websocket handler failed!')

    @gen.coroutine
    def open(self, *varargs):
        self.closed = False
        log.info('WebSocket opened')
        self.getargs = varargs

    @gen.coroutine
    def handle_binary_message(self, message):
        # TODO: implement this!
        raise NotImplementedError

    @gen.coroutine
    def on_message(self, message):
        log.info('Message received:\n' + message)
        try:
            if not isinstance(message, str):
                log.info('binary data')
                yield self.handle_binary_message(message)
            elif not self.local_doc_initialized:
                log.info('Initializing local document...')
                self.session_id = message.split(':')[1]
                self.is_new_session = False
                if self.session_id == 'null':
                    log.info('initializing new session...')
                    self.is_new_session = True
                    self.session_id = self.id
                    self.remotedocument.inline('set_cookie("webalchemy","' + self.session_id + '",3);\n')
                self.tab_id = message.split(':')[3]
                self.is_new_tab = False
                if self.tab_id == '':
                    log.info('initializing new tab...')
                    self.tab_id = self.id
                    self.remotedocument.inline('window.name="' + self.tab_id + '";\n')
                    self.is_new_tab = True
                self.vendor_type = message.split(':')[-1]
                self.remotedocument.set_vendor_prefix(self.vendor_type)
                self.session_data = self.session_data_store.get_store(self.session_id)
                self.tab_data = self.tab_data_store.get_store(self.tab_id)
                r = self.local_doc.initialize(remote_document=self.remotedocument, comm_handler=self,
                                              session_id=self.session_id, tab_id=self.tab_id,
                                              shared_data=self.shared_data, session_data=self.session_data,
                                              tab_data=self.tab_data, is_new_tab=self.is_new_tab,
                                              is_new_session=self.is_new_session,
                                              getargs=self.getargs,
                                              main_html=self.main_html)
                if r is not None:
                    yield r
                self.local_doc_initialized = True
            else:
                if message.startswith('rpc: '):
                    yield self.handle_js_to_py_rpc_message(message)
                elif message != 'done':
                    log.info('Passing message to document inmessage...')
                    r = self.local_doc.inmessage(message)
                    if r is not None:
                        yield r
                elif message != 'done':
                    raise Exception('bad message received: '+str(message))

            yield self.flush_dom()
        except:
            log.exception('Failed handling message:')

    @gen.coroutine
    def send_data(self, text, data):
        # TODO: implement!
        # will have to have a binary format for both text and binary data
        # also change the handling in the client
        raise NotImplementedError

    @gen.coroutine
    def flush_dom(self):
        code = self.remotedocument.pop_all_code()
        if code != '':
            log.info('FLUSHING DOM WITH FOLLOWING MESSAGE:\n' + code)
            # this is good to simulate latency
            #yield async_delay(2)
            self.write_message(code)
        else:
            log.info('FLUSHING DOM: **NOTHING TO FLUSH**')

    @gen.coroutine
    def please_reload(self):
        self.write_message('location.reload();\n')
        self.close()

    @gen.coroutine
    def msg_to_sessions(self, msg, send_to_self=False, to_session_ids=None):
        log.info('Sending message to sessions ' + str(len(self.sharedhandlers)) + ' documents in process:')
        log.info('Message: ' + msg)
        if not to_session_ids:
            lst = self.sharedhandlers.keys()
        else:
            lst = to_session_ids
        for k in lst:
            h = self.sharedhandlers[k]
            if h is not self or send_to_self:
                try:
                    r = h.local_doc.outmessage(self.id, msg)
                    if r is not None:
                        yield r
                    yield h.flush_dom()
                except:
                    log.exception('Failed handling outmessage. Exception:')

    @gen.coroutine
    def on_close(self):
        self.closed = True
        log.info('WebSocket closed')
        log.info('Removing shared doc')
        del self.sharedhandlers[self.id]
        if hasattr(self.local_doc, 'onclose'):
            log.info('Calling local document onclose:')
            try:
                r = self.local_doc.onclose()
                if r is not None:
                    yield r
            except:
                log.exception('Failed handling local document onclose. Exception:')

    @gen.coroutine
    def prepare_session_for_general_reload(self):
        if hasattr(self.local_doc, 'prepare_session_for_general_reload'):
            log.info('preparing session for reload...')
            r = self.local_doc.prepare_session_for_general_reload()
            if r is not None:
                yield r

    @gen.coroutine
    def handle_js_to_py_rpc_message(self, msg):
        log.info('Handling message as js->py RPC call')
        pnum, *etc = msg[5:].split(',')
        pnum = int(pnum)
        args_len = etc[:pnum]
        args_txt = ''.join(etc[pnum:])
        args = []
        curr_pos = 0
        for ln in args_len:
            ln = int(ln)
            args.append(args_txt[curr_pos:curr_pos + ln])
            curr_pos += ln
        rep, *args = args
        wr = self.remotedocument.jsrpcweakrefs[rep]
        fn = wr()
        if fn is None:
            del self.remotedocument.jsrpcweakrefs[rep]
        log.info('Calling local function: ' + str(fn))
        log.info('With args: ' + str(args))
        try:
            r = fn(self.id, *args)
            if r is not None:
                yield r
        except:
            log.exception('JS RPC call failed')

    @gen.coroutine
    def rpc(self, f, *varargs, send_to_self=False, to_session_ids=None, **kwargs):
        log.info('Sending py->py rpc: ' + f.__name__)
        log.info('PARAMS: varargs: ' + str(varargs) + ' kwargs: ' + str(kwargs))
        if not to_session_ids:
            lst = self.sharedhandlers.keys()
        else:
            lst = to_session_ids
        log.info('lst=' + str(lst))
        log.info('self.id=' + self.id)
        for k in lst:
            h = self.sharedhandlers[k]
            if h is not self or send_to_self:
                try:
                    r = getattr(h.local_doc, f.__name__)(self.id, *varargs, **kwargs)
                    if r is not None:
                        yield r
                    yield h.flush_dom()
                except:
                    log.exception('PY RPC call failed for target session: ' + k)