This feature has now been implemented and also resolves
DWR-17, DWR-338, DWR-364, and DWR-433.
Following is a description of the implementation and the changes done, to be used for documentation and release notes:
The client layer (engine.js) is now in full control over the script session id and determines when it wants to assign this id. The id has been split up in two parts; one common for the whole browser process, named the DWR session, and one part unique for each loaded page in a browser window. The DWR session is stored as a DWRSESSIONID session cookie and normally only has to be assigned on the first request of a session. It has nothing to do with the HttpSession. If cookies are disabled this id will be set up for each page load. The client layer takes help from a new __System.generateId() call to obtain a secure and globally unique random string from the server. The page-local part of the id is generated locally on each page load.
The server-side id generator has been replaced with a more secure version and promoted to a plugin:able bean in the container, so there is now an interface in the extend package and the implementation has also moved package-wise. And there is a new entry in defaults.properties.
As the client layer determines the script session id there is no longer any id resync when a script session has timed out on the server side, it will just be recreated with the same id when there is a call from the same page.
Calls from the client will no longer attach the httpSessionId in the batch data as we often will not have access to it (httpOnly). For the CSRF scheme we are instead relying on the first part of the script session id, separated from the window specific part with a slash, which will mirror the DWRSESSIONID cookie value in the same request. Security comes from a CSRF attackers inability to assign this cookie.
Thus, httpSessionId and sessionCookieName handling have been removed from most parts of the code as these are not interesting any longer. The webapp's contextPath has been added though, to be able to set the correct path on the DWRSESSIONID cookie.
Call ordering has been fixed so that there is an internal property _internalOrdered which is used by the script session id logic before we have obtained the DWRSESSIONID. This way we don't need to set/reset any user setting for _ordered. It is also fixed wrt sync calls as it will now let sync calls execute irrespective of the ordered setting. This is our only way to deal with this, as we can't do programmatic blocking ourselves while holding back a sync call. Even though this results in two parallel generateId() calls (one async and one sync), we still protect ourselves from creating two script sessions as only the first of the two returned ids will be activated and used in the following calls, and it is not until this point the script session will be created on the server.
So, when doing the first call from a new browser process, the call logic will obtain the DWRSESSIONID by intercepting the call and inserting an additional call to __System.generateId() before the real call. If the real call is synchronous we will do a synchronous call to generateId() to be able to deliver a blocking experience all the way to the completed real call. When generateId() returns, and before executing the real call, DWRSESSIONID and the script session id will be set up. As this is done transparently together with the first call, the DWRSESSIONID and script session id will not be set up before the first call from a new browser (the first call could be poll, pageLoaded, etc though). If there have been previous calls done from other pages in the same process, the DWRSESSIONID cookie will be set up (if cookies enabled), and the script session id will be available immediately on page load without doing any remote calls.