M webclient/classes_spec/org/mozilla/webclient/DocumentLoadEvent.java

- add event masks for Ajax

M webclient/classes_spec/org/mozilla/webclient/PageInfoListener.java

- Document map values for ajax events

M webclient/src_moz/AjaxListener.cpp
M webclient/src_moz/AjaxListener.h

- Flesh out implementation as much as the underlying browser allows.
  For mozilla, this means start, end, and error.

M webclient/src_moz/EmbedProgress.cpp
M webclient/src_moz/EmbedProgress.h

- move the initialization of the AjaxListener into SetEventRegistration().

- Expose NativeBrowserControl * getter

- Make RequestToURIString public

M webclient/src_share/jni_util.cpp
M webclient/src_share/jni_util.h

- new map keys: readyState, responseText, responseXML

- new event masks START_AJAX, END_AJAX, ERROR_AJAX

M webclient/test/manual/src/classes/org/mozilla/webclient/test/TestBrowser.java

- print map values for AJAX cases.
This commit is contained in:
edburns%acm.org 2007-03-08 13:35:19 +00:00
Родитель fed75fb726
Коммит 598bf8e8ee
9 изменённых файлов: 366 добавлений и 14 удалений

Просмотреть файл

@ -84,6 +84,27 @@ public class DocumentLoadEvent extends WebclientEvent {
public static final long FETCH_INTERRUPT_EVENT_MASK = 1 << 8;
/**
* <p>This event indicates the current fetch is the start of an Ajax
* transaction.</p>
*/
public static final long START_AJAX_EVENT_MASK = 1 << 9;
/**
* <p>This event indicates the current fetch is an Ajax
* transaction in an error state.</p>
*/
public static final long ERROR_AJAX_EVENT_MASK = 1 << 10;
/**
* <p>This event indicates the current fetch is an Ajax
* transaction in that has completed.</p>
*/
public static final long END_AJAX_EVENT_MASK = 1 << 11;
//
// Constructors
//

Просмотреть файл

@ -59,6 +59,65 @@ package org.mozilla.webclient;
* This entry will be a <code>java.util.Map</code> of all the response
* headers.</p></dd>
*
* <dt>For <code>START_AJAX_EVENT_MASK</code> type</dt>
* <dd><p>The map will contain the following keys and values:</p>
* <dl>
* <dt><code>headers</code></dt>
* <dd>a <code>java.util.Map</code> of all the request headers.</dd>
* <dt><code>method</code></dt>
* <dd>the request method for this event.</dd>
* <dt><code>readyState</code></dt>
* <dd>a String of the numerical value of the XMLHTTPRequest readyState</dd>
* </dl>
* </dd>
* <dt>For <code>END_AJAX_EVENT_MASK</code> type</dt>
*
* <dd><p>The map will contain the following keys and values:</p>
* <dl>
* <dt><code>method</code></dt>
* <dd>the request method for this event.</dd>
* <dt>responseXML</dt>
* <dd>a <code>org.w3c.dom.Document</code> instance of the response XML.</dd>
* <dt>responseText</dt>
* <dd>a String instance of the response Text.</dd>
* <dt><code>status</code></dt>
* <dd>the response status string from the server, such as "<code>200
* OK</code>".</dd>
* <dt><code>headers</code></dt>
* <dd>a <code>java.util.Map</code> of all the response headers.</dd>
* <dt><code>method</code></dt>
* <dd>the request method for this event.</dd>
* <dt><code>readyState</code></dt>
* <dd>a String of the numerical value of the XMLHTTPRequest readyState</dd>
* </dl>
* </dl>
*
*

Просмотреть файл

@ -19,19 +19,34 @@
* Ed Burns <edburns@acm.org>
*/
#include <stdlib.h>
#include "AjaxListener.h"
#include "EmbedProgress.h"
#include "nsXPIDLString.h"
#include "nsString.h"
#include "nsServiceManagerUtils.h"
#include "nsIObserverService.h"
#include "nsIHttpChannel.h"
#include "nsIRequest.h"
#include "nsIXMLHTTPRequest.h"
#include "nsIInterfaceRequestor.h"
#include "nsIDOMEvent.h"
#include "NativeBrowserControl.h"
#include "NativeWrapperFactory.h"
#include "HttpHeaderVisitorImpl.h"
#include "jni_util.h"
NS_IMPL_ISUPPORTS1(AjaxListener, nsIObserver)
#define LOADSTR NS_LITERAL_STRING("load")
#define ERRORSTR NS_LITERAL_STRING("error")
NS_IMPL_ISUPPORTS2(AjaxListener,
nsIObserver,
nsIDOMEventListener)
AjaxListener::AjaxListener(EmbedProgress *owner,
JNIEnv *env,
@ -77,7 +92,23 @@ AjaxListener::Observe(nsISupports *aSubject,
if (NS_SUCCEEDED(rv) && iface) {
ajax = do_QueryInterface(iface, &rv);
if (NS_SUCCEEDED(rv) && ajax) {
loadFlags = 0;
rv = ObserveAjax(request, channel, ajax,
AJAX_START);
if (NS_SUCCEEDED(rv)) {
// Hook ourselves up as a DOMEventListener
nsCOMPtr<nsIDOMEventTarget> domTarget =
do_QueryInterface(ajax, &rv);
if (NS_SUCCEEDED(rv) && domTarget) {
rv = domTarget->AddEventListener(LOADSTR,
this,
PR_TRUE);
if (NS_SUCCEEDED(rv)) {
rv = domTarget->AddEventListener(ERRORSTR,
this,
PR_FALSE);
}
}
}
}
else {
// It's ok if we don't have an xmlhttprequest
@ -95,6 +126,47 @@ AjaxListener::Observe(nsISupports *aSubject,
return rv;
}
//
// Methods from nsIDOMEventListener
//
NS_IMETHODIMP
AjaxListener::HandleEvent(nsIDOMEvent *event)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIXMLHttpRequest> ajax;
nsCOMPtr<nsIDOMEventTarget> eventTarget;
if (NS_SUCCEEDED(rv = event->GetTarget(getter_AddRefs(eventTarget)))) {
ajax = do_QueryInterface(eventTarget);
if (ajax) {
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIHttpChannel> httpChannel;
nsCOMPtr<nsIRequest> request = nsnull;
nsAutoString type;
AJAX_STATE state;
rv = ajax->GetChannel(getter_AddRefs(channel));
if (NS_SUCCEEDED(rv) && channel) {
httpChannel = do_QueryInterface(channel);
if (httpChannel) {
request = do_QueryInterface(channel);
if (request) {
rv = event->GetType(type);
if (NS_SUCCEEDED(rv)) {
state = type.EqualsIgnoreCase("load", 4) ?
AJAX_END : AJAX_ERROR;
rv = ObserveAjax(request, httpChannel, ajax,
state);
}
}
}
}
}
}
return rv;
}
//
// Webclient private methods
//
@ -125,3 +197,140 @@ AjaxListener::StopObserving()
return rv;
}
NS_IMETHODIMP
AjaxListener::ObserveAjax(nsIRequest *request,
nsIHttpChannel *channel,
nsIXMLHttpRequest *ajax,
AJAX_STATE state)
{
nsresult rv = NS_OK;
NativeBrowserControl *browserControl = mOwner->GetOwner();
NativeWrapperFactory *wrapperFactory =
browserControl->GetWrapperFactory();
ShareInitContext *pShareContext = &(wrapperFactory->shareContext);
jobject properties = ::util_NewGlobalRef(mJNIEnv,
::util_CreatePropertiesObject(mJNIEnv, (jobject)pShareContext));
PRUint32 responseStatus = 0;
PRInt32 readyState = 0;
char buf[20];
jstring jStr = nsnull;
browserControl->ContentStateChange();
nsXPIDLCString uriString;
nsCAutoString cstr;
EmbedProgress::RequestToURIString(request, getter_Copies(uriString));
const char * uriCStr = (const char *) uriString;
// don't report "about:" URL events.
if (uriString && 5 < uriString.Length() &&
0 == strncmp("about:", uriCStr, 6)) {
return NS_OK;
}
// store the request URI
jStr = (jstring) ::util_NewGlobalRef(mJNIEnv,
::util_NewStringUTF(mJNIEnv,
(nsnull != uriCStr ? uriCStr : "")));
::util_StoreIntoPropertiesObject(mJNIEnv, properties, URI_VALUE, jStr,
(jobject) pShareContext);
// store the headers
HttpHeaderVisitorImpl *visitor =
new HttpHeaderVisitorImpl(mJNIEnv, properties,
(jobject) pShareContext);
if (AJAX_START == state) {
channel->VisitRequestHeaders(visitor);
}
else {
channel->VisitResponseHeaders(visitor);
}
delete visitor;
// store the request method
if (NS_SUCCEEDED(rv = channel->GetRequestMethod(cstr))) {
jStr =
(jstring) ::util_NewGlobalRef(mJNIEnv,
::util_NewStringUTF(mJNIEnv, cstr.get()));
::util_StoreIntoPropertiesObject(mJNIEnv, properties,
METHOD_VALUE, jStr,
(jobject) pShareContext);
}
// store the ready state
if (NS_SUCCEEDED(rv = ajax->GetReadyState(&readyState))) {
WC_ITOA(readyState, buf, 10);
jStr = ::util_NewStringUTF(mJNIEnv, buf);
::util_StoreIntoPropertiesObject(mJNIEnv, properties, READY_STATE_KEY,
(jobject) jStr,
(jobject) pShareContext);
}
if (AJAX_END == state || AJAX_ERROR == state) {
nsAutoString autoString;
// store the response status
if (NS_SUCCEEDED(rv = ajax->GetStatus(&responseStatus))){
if (NS_SUCCEEDED(rv = ajax->GetStatusText(cstr))) {
autoString.AppendInt(responseStatus);
autoString.AppendWithConversion(" ");
autoString.AppendWithConversion(cstr.get());
jStr = (jstring) ::util_NewGlobalRef(mJNIEnv,
::util_NewString(mJNIEnv,
autoString.get(),
autoString.Length()));
::util_StoreIntoPropertiesObject(mJNIEnv, properties,
STATUS_VALUE, jStr,
(jobject) pShareContext);
}
}
// store the response text
if (NS_SUCCEEDED(rv = ajax->GetResponseText(autoString))) {
jStr = (jstring) ::util_NewGlobalRef(mJNIEnv,
::util_NewString(mJNIEnv,
autoString.get(),
autoString.Length()));
::util_StoreIntoPropertiesObject(mJNIEnv, properties,
RESPONSE_TEXT_KEY, jStr,
(jobject) pShareContext);
}
}
DOCUMENT_LOADER_EVENT_MASK_NAMES maskValue = END_AJAX_EVENT_MASK;
switch (state) {
case AJAX_START:
maskValue = START_AJAX_EVENT_MASK;
break;
case AJAX_END:
maskValue = END_AJAX_EVENT_MASK;
break;
case AJAX_ERROR:
maskValue = ERROR_AJAX_EVENT_MASK;
break;
default:
PR_ASSERT(PR_FALSE);
break;
}
::util_SendEventToJava(nsnull,
mEventRegistration,
DOCUMENT_LOAD_LISTENER_CLASSNAME,
DocumentLoader_maskValues[maskValue],
properties);
return NS_OK;
}
/*******************
**********/

Просмотреть файл

@ -24,16 +24,27 @@
#include "nsIObserver.h"
#include "nsIDOMEventListener.h"
#include "jni.h"
class EmbedProgress;
class nsIXMLHttpRequest;
class nsIHttpChannel;
class nsIRequest;
class AjaxListener : public nsIObserver
class AjaxListener : public nsIObserver, public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIDOMEVENTLISTENER
enum AJAX_STATE {
AJAX_START,
AJAX_END,
AJAX_ERROR
};
AjaxListener(EmbedProgress *owner,
JNIEnv *env, jobject eventRegistration);
@ -43,6 +54,12 @@ public:
NS_IMETHOD StopObserving(void);
private:
NS_IMETHOD ObserveAjax(nsIRequest *request,
nsIHttpChannel *channel,
nsIXMLHttpRequest *ajax,
AJAX_STATE state);
EmbedProgress* mOwner;
JNIEnv *mJNIEnv;
jobject mEventRegistration;

Просмотреть файл

@ -90,15 +90,6 @@ EmbedProgress::SetEventRegistration(jobject yourEventRegistration)
::util_ThrowExceptionToJava(env, "Exception: EmbedProgress->SetEventRegistration(): can't create NewGlobalRef\n\tfor eventRegistration");
rv = NS_ERROR_FAILURE;
}
return rv;
}
nsresult
EmbedProgress::SetCapturePageInfo(jboolean newState)
{
mCapturePageInfo = newState;
nsresult rv = NS_OK;
AjaxListener *observer = nsnull;
rv = GetAjaxListener(&observer);
if (observer && NS_SUCCEEDED(rv)) {
@ -109,6 +100,14 @@ EmbedProgress::SetCapturePageInfo(jboolean newState)
observer->StopObserving();
}
}
return rv;
}
nsresult
EmbedProgress::SetCapturePageInfo(jboolean newState)
{
mCapturePageInfo = newState;
return NS_OK;
}
@ -479,6 +478,11 @@ EmbedProgress::OnSecurityChange(nsIWebProgress *aWebProgress,
return NS_OK;
}
NativeBrowserControl* EmbedProgress::GetOwner()
{
return mOwner;
}
NS_IMETHODIMP
EmbedProgress::GetAjaxListener(AjaxListener* *result)
{

Просмотреть файл

@ -47,13 +47,14 @@ class EmbedProgress : public nsIWebProgressListener,
NS_DECL_NSIWEBPROGRESSLISTENER
NativeBrowserControl *GetOwner();
static void RequestToURIString (nsIRequest *aRequest, char **aString);
private:
NS_IMETHOD GetAjaxListener(AjaxListener** result);
NS_IMETHOD RemoveAjaxListener(void);
static void RequestToURIString (nsIRequest *aRequest, char **aString);
NativeBrowserControl *mOwner;
AjaxListener *mAjaxListener;

Просмотреть файл

@ -55,6 +55,9 @@ jobject SCREEN_X_KEY;
jobject SCREEN_Y_KEY;
jobject CLIENT_X_KEY;
jobject CLIENT_Y_KEY;
jobject READY_STATE_KEY;
jobject RESPONSE_TEXT_KEY;
jobject RESPONSE_XML_KEY;
jobject CHAR_CODE;
jobject KEY_CODE;
jobject ALT_KEY;
@ -104,6 +107,9 @@ char * DocumentLoader_maskNames[] = {
STATUS_URL_LOAD_EVENT_MASK_VALUE,
UNKNOWN_CONTENT_EVENT_MASK_VALUE,
FETCH_INTERRUPT_EVENT_MASK_VALUE,
START_AJAX_EVENT_MASK_VALUE,
ERROR_AJAX_EVENT_MASK_VALUE,
END_AJAX_EVENT_MASK_VALUE,
nsnull
};
@ -167,6 +173,21 @@ jboolean util_InitStringConstants()
::util_NewStringUTF(env, "ClientY")))) {
return JNI_FALSE;
}
if (nsnull == (READY_STATE_KEY =
::util_NewGlobalRef(env, (jobject)
::util_NewStringUTF(env, "readyState")))) {
return JNI_FALSE;
}
if (nsnull == (RESPONSE_TEXT_KEY =
::util_NewGlobalRef(env, (jobject)
::util_NewStringUTF(env, "responseText")))) {
return JNI_FALSE;
}
if (nsnull == (RESPONSE_XML_KEY =
::util_NewGlobalRef(env, (jobject)
::util_NewStringUTF(env, "responseXML")))) {
return JNI_FALSE;
}
if (nsnull == (CHAR_CODE =
::util_NewGlobalRef(env, (jobject)
::util_NewStringUTF(env, "KeyChar")))) {

Просмотреть файл

@ -70,6 +70,9 @@ extern jobject SCREEN_X_KEY;
extern jobject SCREEN_Y_KEY;
extern jobject CLIENT_X_KEY;
extern jobject CLIENT_Y_KEY;
extern jobject READY_STATE_KEY;
extern jobject RESPONSE_TEXT_KEY;
extern jobject RESPONSE_XML_KEY;
extern jobject CHAR_CODE;
extern jobject KEY_CODE;
extern jobject ALT_KEY;
@ -164,6 +167,9 @@ typedef enum {
#define STATUS_URL_LOAD_EVENT_MASK_VALUE "STATUS_URL_LOAD_EVENT_MASK"
#define UNKNOWN_CONTENT_EVENT_MASK_VALUE "UNKNOWN_CONTENT_EVENT_MASK"
#define FETCH_INTERRUPT_EVENT_MASK_VALUE "FETCH_INTERRUPT_EVENT_MASK"
#define START_AJAX_EVENT_MASK_VALUE "START_AJAX_EVENT_MASK"
#define ERROR_AJAX_EVENT_MASK_VALUE "ERROR_AJAX_EVENT_MASK"
#define END_AJAX_EVENT_MASK_VALUE "END_AJAX_EVENT_MASK"
#define MOUSE_DOWN_EVENT_MASK_VALUE "MOUSE_DOWN_EVENT_MASK"
#define MOUSE_UP_EVENT_MASK_VALUE "MOUSE_UP_EVENT_MASK"
@ -186,6 +192,9 @@ typedef enum {
STATUS_URL_LOAD_EVENT_MASK,
UNKNOWN_CONTENT_EVENT_MASK,
FETCH_INTERRUPT_EVENT_MASK,
START_AJAX_EVENT_MASK,
ERROR_AJAX_EVENT_MASK,
END_AJAX_EVENT_MASK,
NUMBER_OF_DOCUMENT_LOADER_MASK_NAMES
} DOCUMENT_LOADER_EVENT_MASK_NAMES;

Просмотреть файл

@ -241,6 +241,17 @@ public class TestBrowser extends JPanel {
if (event instanceof DocumentLoadEvent) {
System.out.println("URI: " + map.get("URI"));
switch ((int) event.getType()) {
case ((int) DocumentLoadEvent.END_AJAX_EVENT_MASK):
System.out.println("status: " +
map.get("status"));
System.out.println("responseText: " +
map.get("responseText"));
// INTENTIONAL FALL THROUGH
case ((int) DocumentLoadEvent.START_AJAX_EVENT_MASK):
System.out.println("requestMethod: " +
map.get("method"));
// INTENTIONAL FALL THROUGH
case ((int) DocumentLoadEvent.START_URL_LOAD_EVENT_MASK):
System.out.println("requestMethod: " +
map.get("method"));