/* * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.xhr.client; import com.google.gwt.core.client.JavaScriptObject; /** * The native XMLHttpRequest object. Most applications should use the higher- * level {@link com.google.gwt.http.client.RequestBuilder} class unless they * need specific functionality provided by the XMLHttpRequest object. * * See <a href="http://www.w3.org/TR/XMLHttpRequest/" * >http://www.w3.org/TR/XMLHttpRequest/</a>/ */ public class XMLHttpRequest extends JavaScriptObject { /* * NOTE: Testing discovered that for some bizarre reason, on Mozilla, the * JavaScript <code>XmlHttpRequest.onreadystatechange</code> handler * function maybe still be called after it is deleted. The theory is that the * callback is cached somewhere. Setting it to null or an empty function does * seem to work properly, though. * * On IE, there are two problems: Setting onreadystatechange to null (as * opposed to an empty function) sometimes throws an exception. With * particular (rare) versions of jscript.dll, setting onreadystatechange from * within onreadystatechange causes a crash. Setting it from within a timeout * fixes this bug (see issue 1610). * * End result: *always* set onreadystatechange to an empty function (never to * null). Never set onreadystatechange from within onreadystatechange (always * in a setTimeout()). */ /** * When constructed, the XMLHttpRequest object must be in the UNSENT state. */ public static final int UNSENT = 0; /** * The OPENED state is the state of the object when the open() method has been * successfully invoked. During this state request headers can be set using * setRequestHeader() and the request can be made using send(). */ public static final int OPENED = 1; /** * The HEADERS_RECEIVED state is the state of the object when all response * headers have been received. */ public static final int HEADERS_RECEIVED = 2; /** * The LOADING state is the state of the object when the response entity body * is being received. */ public static final int LOADING = 3; /** * The DONE state is the state of the object when either the data transfer has * been completed or something went wrong during the transfer (infinite * redirects for instance). */ public static final int DONE = 4; /** * Creates an XMLHttpRequest object. * * @return the created object */ public static native XMLHttpRequest create() /*-{ // Don't check window.XMLHttpRequest, because it can // cause cross-site problems on IE8 if window's URL // is javascript:'' . if ($wnd.XMLHttpRequest) { return new $wnd.XMLHttpRequest(); } else { try { return new $wnd.ActiveXObject('MSXML2.XMLHTTP.3.0'); } catch (e) { return new $wnd.ActiveXObject("Microsoft.XMLHTTP"); } } }-*/; protected XMLHttpRequest() { } /** * Aborts the current request. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#abort" * >http://www.w3.org/TR/XMLHttpRequest/#abort</a>. */ public final native void abort() /*-{ this.abort(); }-*/; /** * Clears the {@link ReadyStateChangeHandler}. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#onreadystatechange" * >http://www.w3.org/TR/XMLHttpRequest/#onreadystatechange</a>. * * @see #clearOnReadyStateChange() */ public final native void clearOnReadyStateChange() /*-{ var self = this; $wnd.setTimeout(function() { // Using a function literal here leaks memory on ie6 // Using the same function object kills HtmlUnit self.onreadystatechange = new Function(); }, 0); }-*/; /** * Gets all the HTTP response headers, as a single string. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#getallresponseheaders" * >http://www.w3.org/TR/XMLHttpRequest/#getallresponseheaders</a>. * * @return the response headers. */ public final native String getAllResponseHeaders() /*-{ return this.getAllResponseHeaders(); }-*/; /** * Get's the current ready-state. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#readystate" * >http://www.w3.org/TR/XMLHttpRequest/#readystate</a>. * * @return the ready-state constant */ public final native int getReadyState() /*-{ return this.readyState; }-*/; /** * Gets an HTTP response header. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#getresponseheader" * >http://www.w3.org/TR/XMLHttpRequest/#getresponseheader</a>. * * @param header the response header to be retrieved * @return the header value */ public final native String getResponseHeader(String header) /*-{ return this.getResponseHeader(header); }-*/; /** * Gets the response text. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#responsetext" * >http://www.w3.org/TR/XMLHttpRequest/#responsetext</a>. * * @return the response text */ public final native String getResponseText() /*-{ return this.responseText; }-*/; /** * Gets the status code. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#status" * >http://www.w3.org/TR/XMLHttpRequest/#status</a>. * * @return the status code */ public final native int getStatus() /*-{ return this.status; }-*/; /** * Gets the status text. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#statustext" * >http://www.w3.org/TR/XMLHttpRequest/#statustext</a>. * * @return the status text */ public final native String getStatusText() /*-{ return this.statusText; }-*/; /** * Opens an asynchronous connection. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#open" * >http://www.w3.org/TR/XMLHttpRequest/#open</a>. * * @param httpMethod the HTTP method to use * @param url the URL to be opened */ public final native void open(String httpMethod, String url) /*-{ this.open(httpMethod, url, true); }-*/; /** * Opens an asynchronous connection. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#open" * >http://www.w3.org/TR/XMLHttpRequest/#open</a>. * * @param httpMethod the HTTP method to use * @param url the URL to be opened * @param user user to use in the URL */ public final native void open(String httpMethod, String url, String user) /*-{ this.open(httpMethod, url, true, user); }-*/; /** * Opens an asynchronous connection. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#open" * >http://www.w3.org/TR/XMLHttpRequest/#open</a>. * * @param httpMethod the HTTP method to use * @param url the URL to be opened * @param user user to use in the URL * @param password password to use in the URL */ public final native void open(String httpMethod, String url, String user, String password) /*-{ this.open(httpMethod, url, true, user, password); }-*/; /** * Initiates a request with no request data. This simply calls * {@link #send(String)} with <code>null</code> as an argument, because the * no-argument <code>send()</code> method is unavailable on Firefox. */ public final void send() { send(null); } /** * Initiates a request with data. If there is no data, specify null. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#send" * >http://www.w3.org/TR/XMLHttpRequest/#send</a>. * * @param requestData the data to be sent with the request */ public final native void send(String requestData) /*-{ this.send(requestData); }-*/; /** * Sets the {@link ReadyStateChangeHandler} to be notified when the object's * ready-state changes. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#onreadystatechange" * >http://www.w3.org/TR/XMLHttpRequest/#onreadystatechange</a>. * * <p> * Note: Applications <em>must</em> call {@link #clearOnReadyStateChange()} * when they no longer need this object, to ensure that it is cleaned up * properly. Failure to do so will result in memory leaks on some browsers. * </p> * * @param handler the handler to be called when the ready state changes * @see #clearOnReadyStateChange() */ public final native void setOnReadyStateChange(ReadyStateChangeHandler handler) /*-{ // The 'this' context is always supposed to point to the xhr object in the // onreadystatechange handler, but we reference it via closure to be extra sure. var _this = this; this.onreadystatechange = $entry(function() { handler.@com.google.gwt.xhr.client.ReadyStateChangeHandler::onReadyStateChange(Lcom/google/gwt/xhr/client/XMLHttpRequest;)(_this); }); }-*/; /** * Sets a request header. * <p> * See <a href="http://www.w3.org/TR/XMLHttpRequest/#setrequestheader" * >http://www.w3.org/TR/XMLHttpRequest/#setrequestheader</a>. * * @param header the header to be set * @param value the header's value */ public final native void setRequestHeader(String header, String value) /*-{ this.setRequestHeader(header, value); }-*/; /** * Opens an asynchronous connection. * * @param httpMethod the HTTP method to use * @param url the URL to be opened * @see http://www.w3.org/TR/XMLHttpRequest/#open */ public final native void openSync(String httpMethod, String url) /*-{ this.open(httpMethod, url, false); }-*/; /** * Opens an asynchronous connection. * * @param httpMethod the HTTP method to use * @param url the URL to be opened * @param user user to use in the URL * @see http://www.w3.org/TR/XMLHttpRequest/#open */ public final native void openSync(String httpMethod, String url, String user) /*-{ this.open(httpMethod, url, false, user); }-*/; /** * Opens an asynchronous connection. * * @param httpMethod the HTTP method to use * @param url the URL to be opened * @param user user to use in the URL * @param password password to use in the URL * @see http://www.w3.org/TR/XMLHttpRequest/#open */ public final native void openSync(String httpMethod, String url, String user, String password) /*-{ this.open(httpMethod, url, false, user, password); }-*/; }