cross-origin XMLHttpRequest doesn't work with redirect
authorbbudge@chromium.org <bbudge@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Mar 2012 07:38:47 +0000 (07:38 +0000)
committerbbudge@chromium.org <bbudge@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Mar 2012 07:38:47 +0000 (07:38 +0000)
https://bugs.webkit.org/show_bug.cgi?id=57600

Reviewed by Adam Barth.

Source/WebCore:

Changes DocumentThreadableLoader to follow the CORS redirect steps when
asynchronously loading a cross origin request with access control. Synchronous
loads should not be affected. Also adds methods to ResourceRequestBase to
clear special request headers that aren't allowed when using access control.
Follows the CORS spec as described in the Latest Editor Draft at:
http://www.w3.org/TR/cors/

Test: http/tests/xmlhttprequest/access-control-and-redirects-async.html

* loader/DocumentThreadableLoader.cpp:
* loader/DocumentThreadableLoader.h:
* platform/network/ResourceRequestBase.cpp:
* platform/network/ResourceRequestBase.h:

LayoutTests:

Adds tests to verify that an asynchronous XHR load that receives a redirect
response follows the CORS redirect steps.
Follows the CORS spec as described in the Latest Editor Draft at:
http://www.w3.org/TR/cors/

* http/tests/security/resources/cors-redirect.php: Removed.
* http/tests/security/xhr-cors-redirect.html: Removed.
* http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt: Added.
* http/tests/xmlhttprequest/access-control-and-redirects-async.html: Added.
* http/tests/xmlhttprequest/resources/redirect-cors.php: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@112217 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/http/tests/security/resources/cors-redirect.php [deleted file]
LayoutTests/http/tests/security/xhr-cors-redirect.html [deleted file]
LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async.html [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/resources/redirect-cors.php [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/loader/DocumentThreadableLoader.cpp
Source/WebCore/loader/DocumentThreadableLoader.h
Source/WebCore/platform/network/ResourceRequestBase.cpp
Source/WebCore/platform/network/ResourceRequestBase.h

index f7457b0..0bc4b1f 100644 (file)
@@ -1,3 +1,21 @@
+2012-03-27  Bill Budge  <bbudge@chromium.org>
+
+        cross-origin XMLHttpRequest doesn't work with redirect
+        https://bugs.webkit.org/show_bug.cgi?id=57600
+
+        Reviewed by Adam Barth.
+
+        Adds tests to verify that an asynchronous XHR load that receives a redirect
+        response follows the CORS redirect steps.
+        Follows the CORS spec as described in the Latest Editor Draft at:
+        http://www.w3.org/TR/cors/
+
+        * http/tests/security/resources/cors-redirect.php: Removed.
+        * http/tests/security/xhr-cors-redirect.html: Removed.
+        * http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt: Added.
+        * http/tests/xmlhttprequest/access-control-and-redirects-async.html: Added.
+        * http/tests/xmlhttprequest/resources/redirect-cors.php: Added.
+
 2012-03-27  Philippe Normand  <pnormand@igalia.com>
 
         Unreviewed, GTK gardening after r112112.
diff --git a/LayoutTests/http/tests/security/resources/cors-redirect.php b/LayoutTests/http/tests/security/resources/cors-redirect.php
deleted file mode 100644 (file)
index 83570bc..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-header("Access-Control-Allow-Origin: http://127.0.0.1:8000");
-header("Location: http://localhost:8000/security/resources/empty.html");
-?>
diff --git a/LayoutTests/http/tests/security/xhr-cors-redirect.html b/LayoutTests/http/tests/security/xhr-cors-redirect.html
deleted file mode 100644 (file)
index bba2510..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<html>
-<head>
-<script>
-if (window.layoutTestController) {
-    layoutTestController.dumpAsText();
-    layoutTestController.waitUntilDone();
-}
-
-function log(msg) {
-    document.getElementById("log").innerHTML += msg + "<br>";
-}
-
-function test() {
-    var xhr = new XMLHttpRequest();
-    var url = "http://localhost:8000/security/resources/cors-redirect.php?no-cache";
-    xhr.open("GET", url, false);
-    try {
-        xhr.send(null);
-
-        if (xhr.status == 200)
-            log("PASS: sync XHR successful");
-        else
-            log("FAIL: sync XHR failed");
-    } catch (e) {
-        log("FAIL: sync XHR failed");
-    }
-
-    xhr = new XMLHttpRequest();
-    xhr.open("GET", url, true);
-    xhr.onreadystatechanged = function(e) {
-        if (xhr.readystate == 4) {
-            if (xhr.status == 200)
-                log("PASS: async XHR successful");
-            else
-                log("FAIL: async XHR failed");
-            if (window.layoutTestController)
-                layoutTestController.notifyDone();
-        }
-    };
-    xhr.onerror = function() {
-        log("FAIL: async XHR failed");
-        if (window.layoutTestController)
-            layoutTestController.notifyDone();
-    };
-    xhr.send(null);
-}
-</script>
-</head>
-<body onload="test()">
-<p>
-Test that a cross-origin XHR involving redirects works correctly. If this test
-passes, you will see a series of PASS messages.
-</p>
-<p>
-Currently not working, see http://webkit.org/b/57600
-</p>
-<div id="log"></div>
-</body>
-</html>
diff --git a/LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt b/LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt
new file mode 100644 (file)
index 0000000..d7195dc
--- /dev/null
@@ -0,0 +1,30 @@
+Tests that asynchronous XMLHttpRequests handle redirects according to the CORS standard.
+
+Testing resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi
+Expecting success: false
+PASS: 0
+Testing resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&  access-control-allow-origin=http://localhost:8000&  access-control-allow-credentials=true
+Expecting success: false
+PASS: 0
+Testing resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow.cgi&  access-control-allow-origin=http://localhost:8000&  access-control-allow-credentials=true
+Expecting success: false
+PASS: 0
+Testing http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi
+Expecting success: false
+PASS: 0
+Testing http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&  access-control-allow-origin=http://localhost:8000
+Expecting success: true
+FAIL: 0
+Testing http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?url=http://username:password@127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&  access-control-allow-origin=http://localhost:8000
+Expecting success: false
+PASS: 0
+Testing http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?url=foo://bar.cgi&  access-control-allow-origin=http://localhost:8000
+Expecting success: false
+PASS: 0
+Testing http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?redirect-preflight=true&  url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&  access-control-allow-origin=*
+Expecting success: false
+PASS: 0
+Testing http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?redirect-preflight=false&  url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&  access-control-allow-origin=*&  access-control-allow-headers=x-webkit
+Expecting success: false
+PASS: 0
+
diff --git a/LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async.html b/LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async.html
new file mode 100644 (file)
index 0000000..d6fa1d3
--- /dev/null
@@ -0,0 +1,109 @@
+<p>Tests that asynchronous XMLHttpRequests handle redirects according to the CORS standard.</p>
+
+<pre id="console"></pre>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+function log(message)
+{
+    document.getElementById('console').appendChild(document.createTextNode(message + '\n'));
+}
+
+function runTestAsync(url, forcePreflight, expectSuccess) {
+    log("Testing " + url);
+    log("Expecting success: " + expectSuccess);
+
+    xhr = new XMLHttpRequest();
+    xhr.open("GET", url, true);
+    if (forcePreflight)
+        xhr.setRequestHeader("x-webkit", "foo");
+
+    xhr.onload = function() {
+        log((expectSuccess ? "PASS" : "FAIL") + ": " + xhr.responseText);
+        nextTest();
+    }
+    xhr.onerror = function() {
+        log((expectSuccess ? "FAIL" : "PASS") + ": " + xhr.status);
+        nextTest();
+    }
+    xhr.send(null);
+}
+
+var simple = false;
+var preflight = true;
+var succeeds = true;
+var fails = false;
+
+var tests = [
+// 1) Test simple same origin requests that receive cross origin redirects.
+
+// Request receives a cross-origin redirect response without CORS headers. The redirect response fails the access check.
+["resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi",
+  simple, fails],
+
+// Request receives a cross-origin redirect response with CORS headers. The redirect response passes the access check,
+// but  the resource response fails its access check because the security origin is a globally unique identifier after
+// the redirect and the same origin XHR has 'allowCredentials' true.
+["resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&\
+  access-control-allow-origin=http://localhost:8000&\
+  access-control-allow-credentials=true",
+  simple, fails],
+
+// Same as above, but to a less permissive resource that only allows the requesting origin.
+["resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow.cgi&\
+  access-control-allow-origin=http://localhost:8000&\
+  access-control-allow-credentials=true",
+  simple, fails],
+
+// 2) Test simple cross origin requests that receive redirects.
+
+// Receives a redirect response without CORS headers. The redirect response fails the access check.
+["http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi",
+  simple, fails],
+
+// Receives a redirect response with CORS headers. The redirect response passes the access check and the resource response
+// passes the access check.
+["http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&\
+  access-control-allow-origin=http://localhost:8000",
+  simple, succeeds],
+
+// Receives a redirect response with a URL containing the userinfo production.
+["http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?url=http://username:password@127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&\
+  access-control-allow-origin=http://localhost:8000",
+  simple, fails],
+
+// Receives a redirect response with a URL with an unsupported scheme.
+["http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?url=foo://bar.cgi&\
+  access-control-allow-origin=http://localhost:8000",
+  simple, fails],
+
+// 3) Test preflighted cross origin requests that receive redirects.
+
+// Receives a redirect response to the preflight request and fails.
+["http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?redirect-preflight=true&\
+  url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&\
+  access-control-allow-origin=*",
+  preflight, fails],
+
+// Successful preflight and receives a redirect response to the actual request and fails.
+["http://127.0.0.1:8000/xmlhttprequest/resources/redirect-cors.php?redirect-preflight=false&\
+  url=http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&\
+  access-control-allow-origin=*&\
+  access-control-allow-headers=x-webkit",
+  preflight, fails],
+]
+
+var currentTest = 0;
+
+function nextTest() {
+    if (currentTest < tests.length)
+        runTestAsync.apply(null, tests[currentTest++]);
+    else if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+nextTest();
+</script>
diff --git a/LayoutTests/http/tests/xmlhttprequest/resources/redirect-cors.php b/LayoutTests/http/tests/xmlhttprequest/resources/redirect-cors.php
new file mode 100644 (file)
index 0000000..e1d2e18
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+    $url = $_GET['url'];
+    $redirect_preflight = $_GET['redirect-preflight'];
+    $access_control_allow_origin = $_GET['access-control-allow-origin'];
+    $access_control_allow_credentials = $_GET['access-control-allow-credentials'];
+    $access_control_allow_headers = $_GET['access-control-allow-headers'];
+
+    if ($_SERVER['REQUEST_METHOD'] == "OPTIONS") {
+        if ($redirect_preflight == "true") {
+            header("HTTP/1.1 302");
+            header("Location: $url");
+        }
+        else {
+            header("HTTP/1.1 200");
+        }
+        header("Access-Control-Allow-Methods: GET");
+        header("Access-Control-Max-Age: 1");
+    } else if ($_SERVER['REQUEST_METHOD'] == "GET") {
+        header("HTTP/1.1 302");
+        header("Location: $url");
+    }
+    if (!is_null($access_control_allow_origin))
+        header("Access-Control-Allow-Origin: $access_control_allow_origin");
+    if (!is_null($access_control_allow_credentials))
+        header("Access-Control-Allow-Credentials: $access_control_allow_credentials");
+    if (!is_null($access_control_allow_headers))
+        header("Access-Control-Allow-Headers: $access_control_allow_headers");
+?>
index 4b43fec..4d460ed 100644 (file)
@@ -1,3 +1,24 @@
+2012-03-27  Bill Budge  <bbudge@chromium.org>
+
+        cross-origin XMLHttpRequest doesn't work with redirect
+        https://bugs.webkit.org/show_bug.cgi?id=57600
+
+        Reviewed by Adam Barth.
+
+        Changes DocumentThreadableLoader to follow the CORS redirect steps when
+        asynchronously loading a cross origin request with access control. Synchronous
+        loads should not be affected. Also adds methods to ResourceRequestBase to
+        clear special request headers that aren't allowed when using access control.
+        Follows the CORS spec as described in the Latest Editor Draft at:
+        http://www.w3.org/TR/cors/
+
+        Test: http/tests/xmlhttprequest/access-control-and-redirects-async.html
+
+        * loader/DocumentThreadableLoader.cpp:
+        * loader/DocumentThreadableLoader.h:
+        * platform/network/ResourceRequestBase.cpp:
+        * platform/network/ResourceRequestBase.h:
+
 2012-03-27  Adam Barth  <abarth@webkit.org>
 
         ImageLoader::m_firedLoadEvent is a confusing name
index c357e80..a10fb70 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -74,6 +74,7 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl
     , m_document(document)
     , m_options(options)
     , m_sameOriginRequest(securityOrigin()->canRequest(request.url()))
+    , m_simpleRequest(true)
     , m_async(blockingBehavior == LoadAsynchronously)
 #if ENABLE(INSPECTOR)
     , m_preflightRequestIdentifier(0)
@@ -84,6 +85,11 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl
     // Setting an outgoing referer is only supported in the async code path.
     ASSERT(m_async || request.httpReferrer().isEmpty());
 
+    makeRequest(request);
+}
+
+void DocumentThreadableLoader::makeRequest(const ResourceRequest& request)
+{
     if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) {
         loadRequest(request, DoSecurityCheck);
         return;
@@ -93,7 +99,7 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl
         m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, request.url().string(), "Cross origin requests are not supported."));
         return;
     }
-    
+
     ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
 
     OwnPtr<ResourceRequest> crossOriginRequest = adoptPtr(new ResourceRequest(request));
@@ -102,6 +108,7 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl
     if ((m_options.preflightPolicy == ConsiderPreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight)
         makeSimpleCrossOriginAccessRequest(*crossOriginRequest);
     else {
+        m_simpleRequest = false;
         m_actualRequest = crossOriginRequest.release();
 
         if (CrossOriginPreflightResultCache::shared().canSkipPreflight(securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields()))
@@ -167,13 +174,48 @@ void DocumentThreadableLoader::redirectReceived(CachedResource* resource, Resour
     ASSERT(m_client);
     ASSERT_UNUSED(resource, resource == m_resource);
 
-    if (!isAllowedRedirect(request.url())) {
-        RefPtr<DocumentThreadableLoader> protect(this);
+    RefPtr<DocumentThreadableLoader> protect(this);
+    bool allowRedirect = false;
+    if (m_options.crossOriginRequestPolicy == UseAccessControl) {
+        // When using access control, only simple cross origin requests are allowed to redirect. The new request URL must have a supported
+        // scheme and not contain the userinfo production. In addition, the redirect response must pass the access control check.
+        if (m_simpleRequest) {
+            String accessControlErrorDescription;
+            allowRedirect = SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())
+                            && request.url().user().isEmpty()
+                            && request.url().pass().isEmpty()
+                            && passesAccessControlCheck(redirectResponse, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription);
+        }
+    } else
+        allowRedirect = isAllowedRedirect(request.url());
+
+    if (allowRedirect) {
+        if (m_options.crossOriginRequestPolicy == UseAccessControl) {
+            if (m_resource)
+                clearResource();
+
+            RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::createFromString(redirectResponse.url());
+            RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::createFromString(request.url());
+            // If the request URL origin is not same origin with the original URL origin, set source origin to a globally unique identifier.
+            if (!originalOrigin->isSameSchemeHostPort(requestOrigin.get()))
+                m_options.securityOrigin = SecurityOrigin::createUnique();
+            m_sameOriginRequest = securityOrigin()->canRequest(request.url());
+
+            // Remove any headers that may have been added by the network layer that cause access control to fail.
+            request.clearHTTPContentType();
+            request.clearHTTPReferrer();
+            request.clearHTTPOrigin();
+            request.clearHTTPUserAgent();
+            request.clearHTTPAccept();
+            makeRequest(request);
+        } else {
+            // If not using access control, allow clients to audit the redirect.
+            if (m_client->isDocumentThreadableLoaderClient())
+                static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequest(request, redirectResponse);
+        }
+    } else {
         m_client->didFailRedirectCheck();
         request = ResourceRequest();
-    } else {
-        if (m_client->isDocumentThreadableLoaderClient())
-            static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequest(request, redirectResponse);
     }
 }
 
@@ -377,9 +419,6 @@ bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url)
     if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests)
         return true;
 
-    // FIXME: We need to implement access control for each redirect. This will require some refactoring though, because the code
-    // that processes redirects doesn't know about access control and expects a synchronous answer from its client about whether
-    // a redirect should proceed.
     return m_sameOriginRequest && securityOrigin()->canRequest(url);
 }
 
index 236ae74..5a0b6c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -89,6 +89,7 @@ namespace WebCore {
         void didReceiveResponse(unsigned long identifier, const ResourceResponse&);
         void didFinishLoading(unsigned long identifier, double finishTime);
         void didFail(const ResourceError&);
+        void makeRequest(const ResourceRequest&);
         void makeSimpleCrossOriginAccessRequest(const ResourceRequest& request);
         void makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request);
         void preflightSuccess();
@@ -104,6 +105,7 @@ namespace WebCore {
         Document* m_document;
         ThreadableLoaderOptions m_options;
         bool m_sameOriginRequest;
+        bool m_simpleRequest;
         bool m_async;
         OwnPtr<ResourceRequest> m_actualRequest;  // non-null during Access Control preflight checks
 
index 23ece24..43a64e9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2003, 2006 Apple Computer, Inc.  All rights reserved.
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -251,6 +251,16 @@ void ResourceRequestBase::clearHTTPAuthorization()
         m_platformRequestUpdated = false;
 }
 
+void ResourceRequestBase::clearHTTPContentType()
+{
+    updateResourceRequest(); 
+
+    m_httpHeaderFields.remove("Content-Type");
+
+    if (url().protocolIsInHTTPFamily())
+        m_platformRequestUpdated = false;
+}
+
 void ResourceRequestBase::clearHTTPReferrer()
 {
     updateResourceRequest(); 
@@ -271,6 +281,26 @@ void ResourceRequestBase::clearHTTPOrigin()
         m_platformRequestUpdated = false;
 }
 
+void ResourceRequestBase::clearHTTPUserAgent()
+{
+    updateResourceRequest(); 
+
+    m_httpHeaderFields.remove("User-Agent");
+
+    if (url().protocolIsInHTTPFamily())
+        m_platformRequestUpdated = false;
+}
+
+void ResourceRequestBase::clearHTTPAccept()
+{
+    updateResourceRequest(); 
+
+    m_httpHeaderFields.remove("Accept");
+
+    if (url().protocolIsInHTTPFamily())
+        m_platformRequestUpdated = false;
+}
+
 void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3)
 {
     updateResourceRequest(); 
index 0b154d6..86dd62e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2003, 2006 Apple Computer, Inc.  All rights reserved.
  * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -88,7 +88,8 @@ namespace WebCore {
 
         String httpContentType() const { return httpHeaderField("Content-Type");  }
         void setHTTPContentType(const String& httpContentType) { setHTTPHeaderField("Content-Type", httpContentType); }
-        
+        void clearHTTPContentType();
+
         String httpReferrer() const { return httpHeaderField("Referer"); }
         void setHTTPReferrer(const String& httpReferrer) { setHTTPHeaderField("Referer", httpReferrer); }
         void clearHTTPReferrer();
@@ -99,9 +100,11 @@ namespace WebCore {
 
         String httpUserAgent() const { return httpHeaderField("User-Agent"); }
         void setHTTPUserAgent(const String& httpUserAgent) { setHTTPHeaderField("User-Agent", httpUserAgent); }
+        void clearHTTPUserAgent();
 
         String httpAccept() const { return httpHeaderField("Accept"); }
         void setHTTPAccept(const String& httpAccept) { setHTTPHeaderField("Accept", httpAccept); }
+        void clearHTTPAccept();
 
         void setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2 = String(), const String& encoding3 = String());