diff --git a/examples/desktop_app/README.md b/examples/desktop_app/README.md
new file mode 100644
index 00000000..f9054fb4
--- /dev/null
+++ b/examples/desktop_app/README.md
@@ -0,0 +1,2 @@
+This example demonstrates the use of embedded Vision2 web browser component, and embedded EWF server (using nino).
+
diff --git a/examples/desktop_app/desktop_app.ecf b/examples/desktop_app/desktop_app.ecf
new file mode 100644
index 00000000..78fd6e17
--- /dev/null
+++ b/examples/desktop_app/desktop_app.ecf
@@ -0,0 +1,28 @@
+
+
+ Vision2+web browser widget+embedded web service
+
+ This example demonstrates how to build a vision2 desktop application that embed a web browser accessing the service of an embedded web service.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /EIFGENs$
+ /CVS$
+ /.svn$
+
+
+
+
diff --git a/examples/desktop_app/files/index.html b/examples/desktop_app/files/index.html
new file mode 100644
index 00000000..345e6aef
--- /dev/null
+++ b/examples/desktop_app/files/index.html
@@ -0,0 +1 @@
+Test
diff --git a/examples/desktop_app/home.html b/examples/desktop_app/home.html
new file mode 100644
index 00000000..26e7c6e2
--- /dev/null
+++ b/examples/desktop_app/home.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+This is a local file test with js
back to homeLet AJAX change this text
+
+
+
diff --git a/examples/desktop_app/src/app_embedded_web_service.e b/examples/desktop_app/src/app_embedded_web_service.e
new file mode 100644
index 00000000..e9ebed88
--- /dev/null
+++ b/examples/desktop_app/src/app_embedded_web_service.e
@@ -0,0 +1,230 @@
+note
+ description: "Summary description for {APP_EMBEDDED_WEB_SERVICE}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ APP_EMBEDDED_WEB_SERVICE
+
+inherit
+ EMBEDDED_WEB_SERVICE
+ redefine
+ make
+ end
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ do
+ Precursor
+ create request_exit_operation_actions
+ local_connection_restriction_enabled := True
+ end
+
+feature -- Execution
+
+ request_exit_operation_actions: ACTION_SEQUENCE [TUPLE]
+
+ execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Execute the request
+ -- See `req.input' for input stream
+ -- `req.meta_variables' for the CGI meta variable
+ -- and `res' for output buffer
+ local
+ router: WSF_ROUTER
+ sess: detachable WSF_ROUTER_SESSION
+ m: WSF_HTML_PAGE_RESPONSE
+ b: STRING
+ fs: WSF_FILE_SYSTEM_HANDLER
+ do
+ create router.make (3)
+ router.handle ("/test/{var}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_test))
+ router.handle ("/env", create {WSF_URI_AGENT_HANDLER}.make (agent handle_env))
+ router.handle ("/exit", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_exit))
+ create fs.make_with_path ((create {EXECUTION_ENVIRONMENT}).current_working_path.extended ("files"))
+ router.handle ("/files", fs)
+ create sess
+ router.dispatch (req, res, sess)
+ if not sess.dispatched then
+ create m.make
+ create b.make_from_string ("Hello Eiffel desktop user
")
+ b.append ("test")
+ b.append ("env")
+ b.append ("files")
+ b.append ("exit")
+ m.set_body (b)
+ res.send (m)
+ end
+ end
+
+ handle_test (req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ m: WSF_HTML_PAGE_RESPONSE
+ b: STRING
+ l_name: READABLE_STRING_32
+ do
+ if attached {WSF_STRING} req.item ("var") as p_name then
+ l_name := p_name.value
+ else
+ l_name := {STRING_32} "Embedded web service and web_browser in vision2 application"
+ end
+ create m.make
+ create b.make_from_string ("This is a test about "+ m.html_encoded_string (l_name) +"
")
+ b.append ("back to home")
+ if l_name.is_case_insensitive_equal_general ("start") then
+ b.append ("test javascript+ajax")
+ elseif l_name.is_case_insensitive_equal_general ("js") then
+ b.append ("[
+ Let AJAX change this text
+
+
+ ]")
+ m.add_javascript_content ("[
+ function loadXMLDoc()
+ {
+ var xmlhttp;
+ if (window.XMLHttpRequest)
+ {// code for IE7+, Firefox, Chrome, Opera, Safari
+ xmlhttp=new XMLHttpRequest();
+ }
+ else
+ {// code for IE6, IE5
+ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ xmlhttp.onreadystatechange=function()
+ {
+ if (xmlhttp.readyState==4 && xmlhttp.status==200)
+ {
+ document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
+ }
+ }
+ xmlhttp.open("GET","/test/ajax.txt",true);
+ xmlhttp.send();
+ }
+ ]")
+ elseif l_name.is_case_insensitive_equal_general ("ajax.txt") then
+ b := "This is AJAX response ... from " + req.absolute_script_url ("")
+ end
+ m.set_body (b)
+ res.send (m)
+ end
+
+ handle_env (req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ s: STRING_8
+ p: WSF_PAGE_RESPONSE
+ v: STRING_8
+ do
+ create s.make (2048)
+ s.append ("**DEBUG**%N")
+ req.set_raw_input_data_recorded (True)
+
+ append_iterable_to ("Meta variables:", req.meta_variables, s)
+ s.append_character ('%N')
+
+ append_iterable_to ("Path parameters", req.path_parameters, s)
+ s.append_character ('%N')
+
+ append_iterable_to ("Query parameters", req.query_parameters, s)
+ s.append_character ('%N')
+
+ append_iterable_to ("Form parameters", req.form_parameters, s)
+ s.append_character ('%N')
+
+ if attached req.content_type as l_type then
+ s.append ("Content: type=" + l_type.debug_output)
+ s.append (" length=")
+ s.append_natural_64 (req.content_length_value)
+ s.append_character ('%N')
+ create v.make (req.content_length_value.to_integer_32)
+ req.read_input_data_into (v)
+ across
+ v.split ('%N') as v_cursor
+ loop
+ s.append (" |")
+ s.append (v_cursor.item)
+ s.append_character ('%N')
+ end
+ end
+
+ create p.make_with_body (s)
+ p.header.put_content_type_text_plain
+ res.send (p)
+ end
+
+ handle_exit (req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ m: WSF_HTML_PAGE_RESPONSE
+ b: STRING
+ do
+ create m.make
+ create b.make_from_string ("Embedded server is about to shutdown
")
+ b.append ("back to home")
+ m.set_body (b)
+ res.send (m)
+ if attached {WGI_NINO_CONNECTOR} req.wgi_connector as nino then
+ nino.server.shutdown_server
+ end
+ request_exit_operation_actions.call (Void)
+ end
+
+feature {NONE} -- Implementation
+
+ append_iterable_to (a_title: READABLE_STRING_8; it: detachable ITERABLE [WSF_VALUE]; s: STRING_8)
+ local
+ n: INTEGER
+ t: READABLE_STRING_8
+ v: READABLE_STRING_8
+ do
+ s.append (a_title)
+ s.append_character (':')
+ if it /= Void then
+ across it as c loop
+ n := n + 1
+ end
+ if n = 0 then
+ s.append (" empty")
+ s.append_character ('%N')
+ else
+ s.append_character ('%N')
+ across
+ it as c
+ loop
+ s.append (" - ")
+ s.append (c.item.url_encoded_name)
+ t := c.item.generating_type
+ if t.same_string ("WSF_STRING") then
+ else
+ s.append_character (' ')
+ s.append_character ('{')
+ s.append (t)
+ s.append_character ('}')
+ end
+ s.append_character ('=')
+ v := c.item.string_representation.as_string_8
+ if v.has ('%N') then
+ s.append_character ('%N')
+ across
+ v.split ('%N') as v_cursor
+ loop
+ s.append (" |")
+ s.append (v_cursor.item)
+ s.append_character ('%N')
+ end
+ else
+ s.append (v)
+ s.append_character ('%N')
+ end
+ end
+ end
+ else
+ s.append (" none")
+ s.append_character ('%N')
+ end
+ end
+
+end
diff --git a/examples/desktop_app/src/desktop_app.e b/examples/desktop_app/src/desktop_app.e
new file mode 100644
index 00000000..85aaf27c
--- /dev/null
+++ b/examples/desktop_app/src/desktop_app.e
@@ -0,0 +1,71 @@
+note
+ description: "Objects that represent the Vision2 application.%
+ %The original version of this class has been generated by EiffelBuild."
+ generator: "EiffelBuild"
+ legal: "See notice at end of class."
+ status: "See notice at end of class."
+ date: "$Date: 2012-09-29 01:29:13 +0200 (sam., 29 sept. 2012) $"
+ revision: "$Revision: 89488 $"
+
+
+class
+ DESKTOP_APP
+
+inherit
+ EV_APPLICATION
+
+create
+ make_and_launch
+
+feature {NONE} -- Initialization
+
+ make_and_launch
+ -- Create `Current', build and display `main_window',
+ -- then launch the application.
+ local
+ l_win: like main_window
+ l_embeded_services: APP_EMBEDDED_WEB_SERVICE
+ do
+ default_create
+ create l_win.make
+ main_window := l_win
+ l_win.show
+ create l_embeded_services.make
+ l_embeded_services.set_port_number (0) -- Use first available port number
+
+ l_embeded_services.on_launched_actions.force (agent on_web_service_launched (l_win))
+ l_embeded_services.request_exit_operation_actions.force (agent on_quit)
+ l_embeded_services.launch
+ launch
+ end
+
+ on_quit
+ do
+ if attached main_window as win then
+ win.destroy_and_exit_if_last
+ end
+ end
+
+ on_web_service_launched (a_win: attached like main_window)
+ do
+ add_idle_action_kamikaze (agent a_win.open_link)
+ end
+
+feature {NONE} -- Implementation
+
+ main_window: detachable MAIN_WINDOW
+ -- Main window of `Current'
+
+;note
+ copyright: "Copyright (c) 1984-2009, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 356 Storke Road, Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+
+
+end
diff --git a/examples/desktop_app/src/main_window.e b/examples/desktop_app/src/main_window.e
new file mode 100644
index 00000000..b259db99
--- /dev/null
+++ b/examples/desktop_app/src/main_window.e
@@ -0,0 +1,202 @@
+note
+ description: "Objects that represent an EV_TITLED_WINDOW.%
+ %The original version of this class was generated by EiffelBuild."
+ generator: "EiffelBuild"
+ legal: "See notice at end of class."
+ status: "See notice at end of class."
+ date: "$Date: 2010-08-17 10:49:12 +0200 (mar., 17 août 2010) $"
+ revision: "$Revision: 84189 $"
+
+class
+ MAIN_WINDOW
+
+inherit
+ EV_TITLED_WINDOW
+ redefine
+ create_interface_objects, initialize, is_in_default_state
+ end
+
+ SHARED_EMBEDED_WEB_SERVICE_INFORMATION
+ undefine
+ default_create, copy
+ end
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ -- Creation method
+ do
+ default_create
+ end
+
+ initialize
+ -- Initialize `Current'.
+ do
+ Precursor {EV_TITLED_WINDOW}
+
+ set_title ("Desktop Application (demo embedded EWF+browser)")
+
+ -- Connect events.
+ -- Close the application when an interface close
+ -- request is received on `Current'. i.e. the cross is clicked.
+ close_request_actions.extend (agent destroy_and_exit_if_last)
+
+ -- Call `user_initialization'.
+ user_initialization
+ end
+
+ create_interface_objects
+ -- Create objects
+ do
+ create home_button.make_with_text ("Home")
+ create back_button.make_with_text ("Back")
+ create forth_button.make_with_text ("Forth")
+ create refresh_button.make_with_text ("Refresh")
+ create stop_button.make_with_text ("Stop")
+ create url_text_field.make_with_text ("http://localhost:" + port_number.out)
+ create go_button.make_with_text ("Go")
+
+ create web_browser
+ end
+
+ user_initialization
+ -- Called by `initialize'.
+ -- Any custom user initialization that
+ -- could not be performed in `initialize',
+ -- (due to regeneration of implementation class)
+ -- can be added here.
+ local
+ l_browser_box: EV_VERTICAL_BOX
+ l_server_box: EV_VERTICAL_BOX
+ l_hor_box: EV_HORIZONTAL_BOX
+ vb: EV_VERTICAL_BOX
+ do
+ set_size (800, 600)
+
+ create vb
+ extend (vb)
+ vb.set_border_width (3)
+ vb.set_padding_width (3)
+
+ -- browser part
+ create l_browser_box
+
+ create l_hor_box
+ l_browser_box.extend (l_hor_box)
+ l_browser_box.disable_item_expand (l_hor_box)
+
+ home_button.select_actions.force_extend (agent on_home_button_action)
+ l_hor_box.extend (home_button)
+ l_hor_box.disable_item_expand (home_button)
+
+ back_button.select_actions.force_extend (agent on_back_button_action)
+ l_hor_box.extend (back_button)
+ l_hor_box.disable_item_expand (back_button)
+
+ forth_button.select_actions.force_extend (agent on_forth_button_action)
+ l_hor_box.extend (forth_button)
+ l_hor_box.disable_item_expand (forth_button)
+
+ refresh_button.select_actions.force_extend (agent on_refresh_button_action)
+ l_hor_box.extend (refresh_button)
+ l_hor_box.disable_item_expand (refresh_button)
+
+ stop_button.select_actions.force_extend (agent on_stop_button_action)
+ l_hor_box.extend (stop_button)
+ l_hor_box.disable_item_expand (stop_button)
+
+ l_hor_box.extend (url_text_field)
+
+ go_button.select_actions.force_extend (agent on_go_button_action)
+ l_hor_box.extend (go_button)
+ l_hor_box.disable_item_expand (go_button)
+
+ l_browser_box.extend (web_browser)
+
+ --------------------
+ vb.extend (l_browser_box)
+ end
+
+ is_in_default_state: BOOLEAN
+ do
+ Result := True
+ end
+
+feature -- Basic operation
+
+ open_link
+ do
+ url_text_field.set_text ("http://localhost:" + port_number.out)
+ on_go_button_action
+ end
+
+feature {NONE} -- Implementation
+
+ home_button, go_button, back_button, forth_button, stop_button, refresh_button: EV_BUTTON
+ -- Buttons
+
+ url_text_field: EV_TEXT_FIELD
+ -- URL text field
+
+ on_go_button_action
+ -- Action for `go_button'
+ local
+ l_uri: STRING_32
+ do
+ l_uri := url_text_field.text
+ if l_uri /= Void and then not l_uri.is_empty then
+ web_browser.load_uri (l_uri)
+ else
+ on_home_button_action
+ end
+ end
+
+ on_home_button_action
+ -- Action for `home_button'
+ do
+ web_browser.load_uri ("http://localhost:" + port_number.out)
+ end
+
+ on_back_button_action
+ -- Action for `back_button'
+ do
+ web_browser.back
+ end
+
+ on_forth_button_action
+ -- Action for `forth_button'
+ do
+ web_browser.forth
+ end
+
+ on_refresh_button_action
+ -- Action for `refresh_button'
+ do
+ web_browser.refresh
+ end
+
+ on_stop_button_action
+ -- Action for `stop_button'
+ do
+ web_browser.stop
+ end
+
+ web_browser: EV_WEB_BROWSER
+ -- Web browser widget
+
+;note
+ copyright: "Copyright (c) 1984-2009, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 356 Storke Road, Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+
+
+end
diff --git a/examples/desktop_app/src/service/embedded_web_service.e b/examples/desktop_app/src/service/embedded_web_service.e
new file mode 100644
index 00000000..995f2393
--- /dev/null
+++ b/examples/desktop_app/src/service/embedded_web_service.e
@@ -0,0 +1,114 @@
+note
+ description: "Summary description for {EMBEDDED_WEB_SERVICE}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ EMBEDDED_WEB_SERVICE
+
+inherit
+ THREAD
+ rename
+ make as make_thread,
+ execute as execute_thread
+ end
+
+ WSF_SERVICE
+ rename
+ execute as execute_embedded
+ end
+
+ SHARED_EMBEDED_WEB_SERVICE_INFORMATION
+
+feature -- Initialization
+
+ make
+ do
+ make_thread
+ create on_launched_actions
+ end
+
+feature {NONE} -- Execution
+
+ execute_embedded (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Execute the request
+ -- See `req.input' for input stream
+ -- `req.meta_variables' for the CGI meta variable
+ -- and `res' for output buffer
+ local
+ filter: WSF_AGENT_FILTER
+ m: WSF_PAGE_RESPONSE
+ do
+ if local_connection_restriction_enabled then
+ if
+ attached req.remote_addr as l_remote_addr and then
+ l_remote_addr.is_case_insensitive_equal_general ("127.0.0.1")
+ then
+ execute (req, res)
+ else
+ create m.make_with_body ("Only local connection is allowed")
+ m.set_status_code (403) -- Forbidden
+ res.send (m)
+ end
+ else
+ execute (req, res)
+ end
+ end
+
+ execute_thread
+ local
+ nino: WSF_NINO_SERVICE_LAUNCHER
+ opts: WSF_SERVICE_LAUNCHER_OPTIONS
+ do
+ create opts.default_create
+ opts.set_verbose (True)
+ opts.set_option ("port", port_number)
+ create nino.make (Current, opts)
+ nino.on_launched_actions.force (agent on_launched)
+ nino.launch
+ end
+
+ execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Execute the request
+ -- See `req.input' for input stream
+ -- `req.meta_variables' for the CGI meta variable
+ -- and `res' for output buffer
+ deferred
+ end
+
+ on_launched (conn: WGI_CONNECTOR)
+ do
+ if attached {WGI_NINO_CONNECTOR} conn as nino then
+ set_port_number (nino.port)
+ end
+ on_launched_actions.call (Void)
+ end
+
+feature -- Control
+
+ wait
+ -- Wait for server to be terminated.
+ do
+ join
+ end
+
+feature -- Access
+
+ on_launched_actions: ACTION_SEQUENCE [TUPLE]
+
+feature -- Status report
+
+ local_connection_restriction_enabled: BOOLEAN
+ -- Accept only local connection?
+ --| based on 127.0.0.1 IP
+ --| TO IMPROVE
+
+feature -- Change
+
+ set_local_connection_restriction_enabled (b: BOOLEAN)
+ do
+ local_connection_restriction_enabled := b
+ end
+
+end
diff --git a/examples/desktop_app/src/service/shared_embeded_web_service_information.e b/examples/desktop_app/src/service/shared_embeded_web_service_information.e
new file mode 100644
index 00000000..ba04e855
--- /dev/null
+++ b/examples/desktop_app/src/service/shared_embeded_web_service_information.e
@@ -0,0 +1,27 @@
+note
+ description: "Summary description for {SHARED_EMBEDED_WEB_SERVICE_INFORMATION}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ SHARED_EMBEDED_WEB_SERVICE_INFORMATION
+
+feature -- Access
+
+ port_number: INTEGER
+ do
+ Result := port_number_cell.item
+ end
+
+ set_port_number (a_port: like port_number)
+ do
+ port_number_cell.replace (a_port)
+ end
+
+ port_number_cell: CELL [INTEGER]
+ once ("process")
+ create Result.put (0)
+ end
+
+end