diff --git a/mozilla/java/webclient/classes_spec/org/mozilla/webclient/DocumentLoadEvent.java b/mozilla/java/webclient/classes_spec/org/mozilla/webclient/DocumentLoadEvent.java
index bf7c5356d97..d5a4f0b50c6 100644
--- a/mozilla/java/webclient/classes_spec/org/mozilla/webclient/DocumentLoadEvent.java
+++ b/mozilla/java/webclient/classes_spec/org/mozilla/webclient/DocumentLoadEvent.java
@@ -84,6 +84,27 @@ public class DocumentLoadEvent extends WebclientEvent {
public static final long FETCH_INTERRUPT_EVENT_MASK = 1 << 8;
+ /**
+ *
This event indicates the current fetch is the start of an Ajax
+ * transaction.
+ */
+
+ public static final long START_AJAX_EVENT_MASK = 1 << 9;
+
+ /**
+ * This event indicates the current fetch is an Ajax
+ * transaction in an error state.
+ */
+
+ public static final long ERROR_AJAX_EVENT_MASK = 1 << 10;
+
+ /**
+ * This event indicates the current fetch is an Ajax
+ * transaction in that has completed.
+ */
+
+ public static final long END_AJAX_EVENT_MASK = 1 << 11;
+
//
// Constructors
//
diff --git a/mozilla/java/webclient/classes_spec/org/mozilla/webclient/PageInfoListener.java b/mozilla/java/webclient/classes_spec/org/mozilla/webclient/PageInfoListener.java
index 9cd15ce22c9..3295f8e0479 100644
--- a/mozilla/java/webclient/classes_spec/org/mozilla/webclient/PageInfoListener.java
+++ b/mozilla/java/webclient/classes_spec/org/mozilla/webclient/PageInfoListener.java
@@ -59,6 +59,65 @@ package org.mozilla.webclient;
* This entry will be a java.util.Map of all the response
* headers.
*
+ * For START_AJAX_EVENT_MASK type
+
+ * The map will contain the following keys and values:
+
+ *
+
+ * headers
+
+ * - a
java.util.Map of all the request headers.
+
+ * method
+
+ * - the request method for this event.
+
+ * readyState
+
+ * - a String of the numerical value of the XMLHTTPRequest readyState
+
+ *
+
+ *
+
+ * For END_AJAX_EVENT_MASK type
+ *
+ * The map will contain the following keys and values:
+
+ *
+
+ * method
+
+ * - the request method for this event.
+
+ * - responseXML
+
+ * - a
org.w3c.dom.Document instance of the response XML.
+
+ * - responseText
+
+ * - a String instance of the response Text.
+
+ * status
+
+ * - the response status string from the server, such as "
200
+ * OK".
+
+ * headers
+
+ * - a
java.util.Map of all the response headers.
+
+ * method
+
+ * - the request method for this event.
+
+ * readyState
+
+ * - a String of the numerical value of the XMLHTTPRequest readyState
+
+ *
+
*
*
*
diff --git a/mozilla/java/webclient/src_moz/AjaxListener.cpp b/mozilla/java/webclient/src_moz/AjaxListener.cpp
index 45d8200c75e..f16b0d91a61 100755
--- a/mozilla/java/webclient/src_moz/AjaxListener.cpp
+++ b/mozilla/java/webclient/src_moz/AjaxListener.cpp
@@ -19,19 +19,34 @@
* Ed Burns
*/
+#include
+
#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 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 ajax;
+ nsCOMPtr eventTarget;
+ if (NS_SUCCEEDED(rv = event->GetTarget(getter_AddRefs(eventTarget)))) {
+ ajax = do_QueryInterface(eventTarget);
+ if (ajax) {
+ nsCOMPtr channel;
+ nsCOMPtr httpChannel;
+ nsCOMPtr 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;
+}
+
+
+/*******************
+
+
+
+
+**********/
diff --git a/mozilla/java/webclient/src_moz/AjaxListener.h b/mozilla/java/webclient/src_moz/AjaxListener.h
index eebff88e05d..cd3d97c0a26 100755
--- a/mozilla/java/webclient/src_moz/AjaxListener.h
+++ b/mozilla/java/webclient/src_moz/AjaxListener.h
@@ -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;
diff --git a/mozilla/java/webclient/src_moz/EmbedProgress.cpp b/mozilla/java/webclient/src_moz/EmbedProgress.cpp
index e028288ac5e..3daf9e388e1 100644
--- a/mozilla/java/webclient/src_moz/EmbedProgress.cpp
+++ b/mozilla/java/webclient/src_moz/EmbedProgress.cpp
@@ -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)
{
diff --git a/mozilla/java/webclient/src_moz/EmbedProgress.h b/mozilla/java/webclient/src_moz/EmbedProgress.h
index d10b93e649a..9c58d862758 100644
--- a/mozilla/java/webclient/src_moz/EmbedProgress.h
+++ b/mozilla/java/webclient/src_moz/EmbedProgress.h
@@ -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;
diff --git a/mozilla/java/webclient/src_share/jni_util.cpp b/mozilla/java/webclient/src_share/jni_util.cpp
index 6843280a6e6..b053efd7d76 100644
--- a/mozilla/java/webclient/src_share/jni_util.cpp
+++ b/mozilla/java/webclient/src_share/jni_util.cpp
@@ -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")))) {
diff --git a/mozilla/java/webclient/src_share/jni_util.h b/mozilla/java/webclient/src_share/jni_util.h
index 8fdfb4f51a2..dd41241a7d1 100644
--- a/mozilla/java/webclient/src_share/jni_util.h
+++ b/mozilla/java/webclient/src_share/jni_util.h
@@ -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;
diff --git a/mozilla/java/webclient/test/manual/src/classes/org/mozilla/webclient/test/TestBrowser.java b/mozilla/java/webclient/test/manual/src/classes/org/mozilla/webclient/test/TestBrowser.java
index a4ccc4106cb..19fbf18a6b4 100644
--- a/mozilla/java/webclient/test/manual/src/classes/org/mozilla/webclient/test/TestBrowser.java
+++ b/mozilla/java/webclient/test/manual/src/classes/org/mozilla/webclient/test/TestBrowser.java
@@ -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"));