Changeset 47291 in webkit


Ignore:
Timestamp:
Aug 14, 2009 12:25:37 PM (15 years ago)
Author:
eric@webkit.org
Message:

2009-08-14 Aaron Boodman <aa@chromium.org>

Reviewed by Alexey Proskuryakov.

BUG 28134: Move the remaining parts of Access Control from XMLHttpRequest to ThreadableDocumentLoader.
https://bugs.webkit.org/show_bug.cgi?id=28134

No new tests added since Access Control was already well tested and this is a pure refactor.

  • loader/DocumentThreadableLoader.cpp: Move a lot of the access control code from XHR in, preserving its basic strategy. Also, modify the synchronous path to not be a special case, but reuse more of the async path.

(WebCore::DocumentThreadableLoader::loadResourceSynchronously): Go through the async path and pass additional flags.
(WebCore::DocumentThreadableLoader::create): Group enum params into an options struct.
(WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Ditto.
(WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): Brought mostly from XHR.
(WebCore::DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight): Ditto.
(WebCore::DocumentThreadableLoader::willSendRequest): Handle preflight case.
(WebCore::DocumentThreadableLoader::didReceiveResponse): Ditto.
(WebCore::DocumentThreadableLoader::didFinishLoading): Ditto.
(WebCore::DocumentThreadableLoader::getShouldUseCredentialStorage): Ditto.
(WebCore::DocumentThreadableLoader::preflightSuccess): Preflight handling.
(WebCore::DocumentThreadableLoader::preflightFailure): Ditto.
(WebCore::DocumentThreadableLoader::loadRequest): Common request function that handles async/sync.

  • loader/DocumentThreadableLoader.h: Group enum params into an options struct.
  • loader/ThreadableLoader.cpp: Ditto. (WebCore::ThreadableLoader::create): Ditto. (WebCore::ThreadableLoader::loadResourceSynchronously): Ditto.
  • loader/ThreadableLoader.h: Ditto. (WebCore::ThreadableLoaderOptions::ThreadableLoaderOptions): Ditto.
  • loader/WorkerThreadableLoader.cpp: Ditto. (WebCore::WorkerThreadableLoader::WorkerThreadableLoader):Ditto. (WebCore::WorkerThreadableLoader::loadResourceSynchronously): Ditto. (WebCore::WorkerThreadableLoader::MainThreadBridge::MainThreadBridge): Ditto. (WebCore::WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader): Ditto.
  • loader/WorkerThreadableLoader.h: Ditto. (WebCore::WorkerThreadableLoader::create): Ditto.
  • platform/CrossThreadCopier.h: Allow ThreadableLoaderOptions to be copied across threads. (WebCore::):
  • workers/WorkerScriptLoader.cpp: More enum->struct grouping. (WebCore::WorkerScriptLoader::loadSynchronously): More enum->struct grouping. (WebCore::WorkerScriptLoader::loadAsynchronously): More enum->struct grouping.
  • xml/XMLHttpRequest.cpp: Remove all the access control code and some supporting state. (WebCore::XMLHttpRequest::XMLHttpRequest): Ditto. (WebCore::XMLHttpRequest::createRequest): Ditto. (WebCore::XMLHttpRequest::didFinishLoading): Ditto. (WebCore::XMLHttpRequest::didReceiveResponse): Ditto. (WebCore::XMLHttpRequest::didReceiveData): Ditto.
  • xml/XMLHttpRequest.h: Ditto.
Location:
trunk/WebCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r47288 r47291  
     12009-08-14  Aaron Boodman  <aa@chromium.org>
     2
     3        Reviewed by Alexey Proskuryakov.
     4
     5        BUG 28134: Move the remaining parts of Access Control from XMLHttpRequest to ThreadableDocumentLoader.
     6        https://bugs.webkit.org/show_bug.cgi?id=28134
     7
     8        No new tests added since Access Control was already well tested and this is a pure refactor.
     9
     10        * loader/DocumentThreadableLoader.cpp: Move a lot of the access control code from XHR in, preserving its
     11        basic strategy. Also, modify the synchronous path to not be a special case, but reuse more of the async
     12        path.
     13
     14        (WebCore::DocumentThreadableLoader::loadResourceSynchronously): Go through the async path and pass additional flags.
     15        (WebCore::DocumentThreadableLoader::create): Group enum params into an options struct.
     16        (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Ditto.
     17        (WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): Brought mostly from XHR.
     18        (WebCore::DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight): Ditto.
     19        (WebCore::DocumentThreadableLoader::willSendRequest): Handle preflight case.
     20        (WebCore::DocumentThreadableLoader::didReceiveResponse): Ditto.
     21        (WebCore::DocumentThreadableLoader::didFinishLoading): Ditto.
     22        (WebCore::DocumentThreadableLoader::getShouldUseCredentialStorage): Ditto.
     23        (WebCore::DocumentThreadableLoader::preflightSuccess): Preflight handling.
     24        (WebCore::DocumentThreadableLoader::preflightFailure): Ditto.
     25        (WebCore::DocumentThreadableLoader::loadRequest): Common request function that handles async/sync.
     26        * loader/DocumentThreadableLoader.h: Group enum params into an options struct.
     27        * loader/ThreadableLoader.cpp: Ditto.
     28        (WebCore::ThreadableLoader::create): Ditto.
     29        (WebCore::ThreadableLoader::loadResourceSynchronously): Ditto.
     30        * loader/ThreadableLoader.h: Ditto.
     31        (WebCore::ThreadableLoaderOptions::ThreadableLoaderOptions): Ditto.
     32        * loader/WorkerThreadableLoader.cpp: Ditto.
     33        (WebCore::WorkerThreadableLoader::WorkerThreadableLoader):Ditto.
     34        (WebCore::WorkerThreadableLoader::loadResourceSynchronously): Ditto.
     35        (WebCore::WorkerThreadableLoader::MainThreadBridge::MainThreadBridge): Ditto.
     36        (WebCore::WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader): Ditto.
     37        * loader/WorkerThreadableLoader.h: Ditto.
     38        (WebCore::WorkerThreadableLoader::create): Ditto.
     39        * platform/CrossThreadCopier.h: Allow ThreadableLoaderOptions to be copied across threads.
     40        (WebCore::):
     41        * workers/WorkerScriptLoader.cpp: More enum->struct grouping.
     42        (WebCore::WorkerScriptLoader::loadSynchronously): More enum->struct grouping.
     43        (WebCore::WorkerScriptLoader::loadAsynchronously): More enum->struct grouping.
     44        * xml/XMLHttpRequest.cpp: Remove all the access control code and some supporting state.
     45        (WebCore::XMLHttpRequest::XMLHttpRequest): Ditto.
     46        (WebCore::XMLHttpRequest::createRequest): Ditto.
     47        (WebCore::XMLHttpRequest::didFinishLoading): Ditto.
     48        (WebCore::XMLHttpRequest::didReceiveResponse): Ditto.
     49        (WebCore::XMLHttpRequest::didReceiveData): Ditto.
     50        * xml/XMLHttpRequest.h: Ditto.
     51
    1522009-08-14  Darin Adler  <darin@apple.com>
    253
  • trunk/WebCore/loader/DocumentThreadableLoader.cpp

    r45935 r47291  
    3333
    3434#include "AuthenticationChallenge.h"
     35#include "CrossOriginAccessControl.h"
     36#include "CrossOriginPreflightResultCache.h"
    3537#include "Document.h"
    36 #include "DocumentThreadableLoader.h"
    3738#include "Frame.h"
    3839#include "FrameLoader.h"
     
    4445namespace WebCore {
    4546
    46 void DocumentThreadableLoader::loadResourceSynchronously(Document* document, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials)
    47 {
    48     bool sameOriginRequest = document->securityOrigin()->canRequest(request.url());
    49 
    50     Vector<char> data;
    51     ResourceError error;
    52     ResourceResponse response;
    53     unsigned long identifier = std::numeric_limits<unsigned long>::max();
    54     if (document->frame())
    55         identifier = document->frame()->loader()->loadResourceSynchronously(request, storedCredentials, error, response, data);
    56 
    57     // No exception for file:/// resources, see <rdar://problem/4962298>.
    58     // Also, if we have an HTTP response, then it wasn't a network error in fact.
    59     if (!error.isNull() && !request.url().isLocalFile() && response.httpStatusCode() <= 0) {
    60         client.didFail(error);
    61         return;
    62     }
    63 
    64     // FIXME: This check along with the one in willSendRequest is specific to xhr and
    65     // should be made more generic.
    66     if (sameOriginRequest && !document->securityOrigin()->canRequest(response.url())) {
    67         client.didFailRedirectCheck();
    68         return;
    69     }
    70 
    71     client.didReceiveResponse(response);
    72 
    73     const char* bytes = static_cast<const char*>(data.data());
    74     int len = static_cast<int>(data.size());
    75     client.didReceiveData(bytes, len);
    76 
    77     client.didFinishLoading(identifier);
    78 }
    79 
    80 PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
    81 {
    82     ASSERT(document);
    83     RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
     47void DocumentThreadableLoader::loadResourceSynchronously(Document* document, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
     48{
     49    // The loader will be deleted as soon as this function exits.
     50    RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, &client, LoadSynchronously, request, options));
     51    ASSERT(loader->hasOneRef());
     52}
     53
     54PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options)
     55{
     56    RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, LoadAsynchronously, request, options));
    8457    if (!loader->m_loader)
    8558        loader = 0;
     
    8760}
    8861
    89 DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
     62DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options)
    9063    : m_client(client)
    9164    , m_document(document)
    92     , m_allowStoredCredentials(storedCredentials == AllowStoredCredentials)
     65    , m_options(options)
    9366    , m_sameOriginRequest(document->securityOrigin()->canRequest(request.url()))
    94     , m_denyCrossOriginRedirect(crossOriginRedirectPolicy == DenyCrossOriginRedirect)
     67    , m_async(blockingBehavior == LoadAsynchronously)
    9568{
    9669    ASSERT(document);
    9770    ASSERT(client);
    98     ASSERT(storedCredentials == AllowStoredCredentials || storedCredentials == DoNotAllowStoredCredentials);
    99     ASSERT(crossOriginRedirectPolicy == DenyCrossOriginRedirect || crossOriginRedirectPolicy == AllowCrossOriginRedirect);
    100     m_loader = SubresourceLoader::create(document->frame(), this, request, false, callbacksSetting == SendLoadCallbacks, contentSniff == SniffContent);
     71
     72    if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) {
     73        bool skipCanLoadCheck = false;
     74        loadRequest(request, skipCanLoadCheck);
     75        return;
     76    }
     77
     78    if (m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) {
     79        m_client->didFail(ResourceError());
     80        return;
     81    }
     82   
     83    ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
     84
     85    if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields()))
     86        makeSimpleCrossOriginAccessRequest(request);
     87    else {
     88        m_actualRequest.set(new ResourceRequest(request));
     89        m_actualRequest->setAllowHTTPCookies(m_options.allowCredentials);
     90
     91        if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), request.url(), m_options.allowCredentials, request.httpMethod(), request.httpHeaderFields()))
     92            preflightSuccess();
     93        else
     94            makeCrossOriginAccessRequestWithPreflight(request);
     95    }
     96}
     97
     98void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const ResourceRequest& request)
     99{
     100    ASSERT(isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields()));
     101
     102    // Cross-origin requests are only defined for HTTP. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied.
     103    if (!request.url().protocolInHTTPFamily()) {
     104        m_client->didFail(ResourceError());
     105        return;
     106    }
     107
     108    // Make a copy of the passed request so that we can modify some details.
     109    ResourceRequest crossOriginRequest(request);
     110    crossOriginRequest.removeCredentials();
     111    crossOriginRequest.setAllowHTTPCookies(m_options.allowCredentials);
     112    crossOriginRequest.setHTTPOrigin(m_document->securityOrigin()->toString());
     113
     114    bool skipCanLoadCheck = false;
     115    loadRequest(crossOriginRequest, skipCanLoadCheck);
     116}
     117
     118void DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request)
     119{
     120    ResourceRequest preflightRequest(request.url());
     121    preflightRequest.removeCredentials();
     122    preflightRequest.setHTTPOrigin(m_document->securityOrigin()->toString());
     123    preflightRequest.setAllowHTTPCookies(m_options.allowCredentials);
     124    preflightRequest.setHTTPMethod("OPTIONS");
     125    preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", request.httpMethod());
     126
     127    const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields();
     128
     129    if (requestHeaderFields.size() > 0) {
     130        Vector<UChar> headerBuffer;
     131        HTTPHeaderMap::const_iterator it = requestHeaderFields.begin();
     132        append(headerBuffer, it->first);
     133        ++it;
     134
     135        HTTPHeaderMap::const_iterator end = requestHeaderFields.end();
     136        for (; it != end; ++it) {
     137            headerBuffer.append(',');
     138            headerBuffer.append(' ');
     139            append(headerBuffer, it->first);
     140        }
     141
     142        preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer));
     143        preflightRequest.addHTTPHeaderFields(requestHeaderFields);
     144    }
     145
     146    bool skipCanLoadCheck = false;
     147    loadRequest(preflightRequest, skipCanLoadCheck);
    101148}
    102149
     
    124171
    125172    // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
    126     if (m_denyCrossOriginRedirect && !m_document->securityOrigin()->canRequest(request.url())) {
     173    if (m_options.crossOriginRedirectPolicy == DenyCrossOriginRedirect && !m_document->securityOrigin()->canRequest(request.url())) {
    127174        RefPtr<DocumentThreadableLoader> protect(this);
    128175        m_client->didFailRedirectCheck();
     
    144191    ASSERT_UNUSED(loader, loader == m_loader);
    145192
    146     m_client->didReceiveResponse(response);
     193    if (m_actualRequest) {
     194        if (!passesAccessControlCheck(response, m_options.allowCredentials, m_document->securityOrigin())) {
     195            preflightFailure();
     196            return;
     197        }
     198
     199        OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult(new CrossOriginPreflightResultCacheItem(m_options.allowCredentials));
     200        if (!preflightResult->parse(response)
     201            || !preflightResult->allowsCrossOriginMethod(m_actualRequest->httpMethod())
     202            || !preflightResult->allowsCrossOriginHeaders(m_actualRequest->httpHeaderFields())) {
     203            preflightFailure();
     204            return;
     205        }
     206
     207        CrossOriginPreflightResultCache::shared().appendEntry(m_document->securityOrigin()->toString(), m_actualRequest->url(), preflightResult.release());
     208    } else {
     209        if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) {
     210            if (!passesAccessControlCheck(response, m_options.allowCredentials, m_document->securityOrigin())) {
     211                m_client->didFail(ResourceError());
     212                return;
     213            }
     214        }
     215
     216        m_client->didReceiveResponse(response);
     217    }
    147218}
    148219
     
    159230    ASSERT(loader == m_loader);
    160231    ASSERT(m_client);
    161     m_client->didFinishLoading(loader->identifier());
     232    didFinishLoading(loader->identifier());
     233}
     234
     235void DocumentThreadableLoader::didFinishLoading(unsigned long identifier)
     236{
     237    if (m_actualRequest) {
     238        ASSERT(!m_sameOriginRequest);
     239        ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
     240        preflightSuccess();
     241    } else
     242        m_client->didFinishLoading(identifier);
    162243}
    163244
     
    175256    ASSERT_UNUSED(loader, loader == m_loader);
    176257
    177     if (!m_allowStoredCredentials) {
     258    if (!m_options.allowCredentials) {
    178259        shouldUseCredentialStorage = false;
    179260        return true;
     
    201282}
    202283
     284void DocumentThreadableLoader::preflightSuccess()
     285{
     286    OwnPtr<ResourceRequest> actualRequest;
     287    actualRequest.swap(m_actualRequest);
     288
     289    bool skipCanLoadCheck = true;  // ok to skip load check since we already asked about the preflight request
     290    loadRequest(*actualRequest, skipCanLoadCheck);
     291}
     292
     293void DocumentThreadableLoader::preflightFailure()
     294{
     295    m_client->didFail(ResourceError());
     296}
     297
     298void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, bool skipCanLoadCheck)
     299{
     300    if (m_async) {
     301        // Don't sniff content or send load callbacks for the preflight request.
     302        bool sendLoadCallbacks = m_options.sendLoadCallbacks && !m_actualRequest;
     303        bool sniffContent = m_options.sniffContent && !m_actualRequest;
     304        m_loader = SubresourceLoader::create(m_document->frame(), this, request, skipCanLoadCheck, sendLoadCallbacks, sniffContent);
     305        return;
     306    }
     307   
     308    // FIXME: ThreadableLoaderOptions.sniffContent is not supported for synchronous requests.
     309    StoredCredentials storedCredentials = m_options.allowCredentials ? AllowStoredCredentials : DoNotAllowStoredCredentials;
     310
     311    Vector<char> data;
     312    ResourceError error;
     313    ResourceResponse response;
     314    unsigned long identifier = std::numeric_limits<unsigned long>::max();
     315    if (m_document->frame())
     316        identifier = m_document->frame()->loader()->loadResourceSynchronously(request, storedCredentials, error, response, data);
     317
     318    // No exception for file:/// resources, see <rdar://problem/4962298>.
     319    // Also, if we have an HTTP response, then it wasn't a network error in fact.
     320    if (!error.isNull() && !request.url().isLocalFile() && response.httpStatusCode() <= 0) {
     321        m_client->didFail(error);
     322        return;
     323    }
     324
     325    // FIXME: This check along with the one in willSendRequest is specific to xhr and
     326    // should be made more generic.
     327    if (m_sameOriginRequest && !m_document->securityOrigin()->canRequest(response.url())) {
     328        m_client->didFailRedirectCheck();
     329        return;
     330    }
     331
     332    didReceiveResponse(0, response);
     333
     334    const char* bytes = static_cast<const char*>(data.data());
     335    int len = static_cast<int>(data.size());
     336    didReceiveData(0, bytes, len);
     337
     338    didFinishLoading(identifier);
     339}
     340
    203341} // namespace WebCore
  • trunk/WebCore/loader/DocumentThreadableLoader.h

    r44737 r47291  
    3434#include "SubresourceLoaderClient.h"
    3535#include "ThreadableLoader.h"
     36#include <wtf/OwnPtr.h>
    3637#include <wtf/PassRefPtr.h>
    3738#include <wtf/RefCounted.h>
     
    4546    class DocumentThreadableLoader : public RefCounted<DocumentThreadableLoader>, public ThreadableLoader, private SubresourceLoaderClient  {
    4647    public:
    47         static void loadResourceSynchronously(Document*, const ResourceRequest&, ThreadableLoaderClient&, StoredCredentials);
    48         static PassRefPtr<DocumentThreadableLoader> create(Document*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
     48        static void loadResourceSynchronously(Document*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
     49        static PassRefPtr<DocumentThreadableLoader> create(Document*, ThreadableLoaderClient*, const ResourceRequest&, const ThreadableLoaderOptions&);
    4950        virtual ~DocumentThreadableLoader();
    5051
     
    5960
    6061    private:
    61         DocumentThreadableLoader(Document*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
     62        enum BlockingBehavior {
     63            LoadSynchronously,
     64            LoadAsynchronously
     65        };
     66
     67        DocumentThreadableLoader(Document*, ThreadableLoaderClient*, BlockingBehavior blockingBehavior, const ResourceRequest&, const ThreadableLoaderOptions& options);
     68
    6269        virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse);
    6370        virtual void didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
     
    7279        virtual void receivedCancellation(SubresourceLoader*, const AuthenticationChallenge&);
    7380
     81        void didFinishLoading(unsigned long identifier);
     82        void makeSimpleCrossOriginAccessRequest(const ResourceRequest& request);
     83        void makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request);
     84        void preflightSuccess();
     85        void preflightFailure();
     86
     87        void loadRequest(const ResourceRequest&, bool skipCanLoadCheck);
     88
    7489        RefPtr<SubresourceLoader> m_loader;
    7590        ThreadableLoaderClient* m_client;
    7691        Document* m_document;
    77         bool m_allowStoredCredentials;
     92        ThreadableLoaderOptions m_options;
    7893        bool m_sameOriginRequest;
    79         bool m_denyCrossOriginRedirect;
     94        bool m_async;
     95        OwnPtr<ResourceRequest> m_actualRequest;  // non-null during Access Control preflight checks
    8096    };
    8197
  • trunk/WebCore/loader/ThreadableLoader.cpp

    r44737 r47291  
    4141namespace WebCore {
    4242
    43 PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
     43PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options)
    4444{
    4545    ASSERT(client);
     
    4848#if ENABLE(WORKERS)
    4949    if (context->isWorkerContext())
    50         return WorkerThreadableLoader::create(static_cast<WorkerContext*>(context), client, WorkerRunLoop::defaultMode(), request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy);
     50        return WorkerThreadableLoader::create(static_cast<WorkerContext*>(context), client, WorkerRunLoop::defaultMode(), request, options);
    5151#endif // ENABLE(WORKERS)
    5252
    5353    ASSERT(context->isDocument());
    54     return DocumentThreadableLoader::create(static_cast<Document*>(context), client, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy);
     54    return DocumentThreadableLoader::create(static_cast<Document*>(context), client, request, options);
    5555}
    5656
    57 void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials)
     57void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
    5858{
    5959    ASSERT(context);
     
    6161#if ENABLE(WORKERS)
    6262    if (context->isWorkerContext()) {
    63         WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, storedCredentials, DenyCrossOriginRedirect);
     63        WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, options);
    6464        return;
    6565    }
     
    6767
    6868    ASSERT(context->isDocument());
    69     DocumentThreadableLoader::loadResourceSynchronously(static_cast<Document*>(context), request, client, storedCredentials);
     69    DocumentThreadableLoader::loadResourceSynchronously(static_cast<Document*>(context), request, client, options);
    7070}
    7171
  • trunk/WebCore/loader/ThreadableLoader.h

    r45891 r47291  
    4444    class ThreadableLoaderClient;
    4545
    46     enum LoadCallbacks {
    47         SendLoadCallbacks,
    48         DoNotSendLoadCallbacks
    49     };
    50 
    51     enum ContentSniff {
    52         SniffContent,
    53         DoNotSniffContent
    54     };
    55 
    5646    enum StoredCredentials {
    5747        AllowStoredCredentials,
    5848        DoNotAllowStoredCredentials
    5949    };
    60 
     50   
     51    enum CrossOriginRequestPolicy {
     52        DenyCrossOriginRequests,
     53        UseAccessControl,
     54        AllowCrossOriginRequests
     55    };
     56   
    6157    enum CrossOriginRedirectPolicy {
    6258        DenyCrossOriginRedirect,
    6359        AllowCrossOriginRedirect
     60    };
     61   
     62    struct ThreadableLoaderOptions {
     63        ThreadableLoaderOptions() : sendLoadCallbacks(false), sniffContent(false), allowCredentials(false), forcePreflight(false), crossOriginRequestPolicy(DenyCrossOriginRequests), crossOriginRedirectPolicy(AllowCrossOriginRedirect) { }
     64        bool sendLoadCallbacks;
     65        bool sniffContent;
     66        bool allowCredentials;  // Whether HTTP credentials and cookies are sent with the request.
     67        bool forcePreflight;  // If AccessControl is used, whether to force a preflight.
     68        CrossOriginRequestPolicy crossOriginRequestPolicy;
     69        CrossOriginRedirectPolicy crossOriginRedirectPolicy;
    6470    };
    6571
     
    6874    class ThreadableLoader : public Noncopyable {
    6975    public:
    70         static void loadResourceSynchronously(ScriptExecutionContext*, const ResourceRequest&, ThreadableLoaderClient&, StoredCredentials);
    71         static PassRefPtr<ThreadableLoader> create(ScriptExecutionContext*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
     76        static void loadResourceSynchronously(ScriptExecutionContext*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
     77        static PassRefPtr<ThreadableLoader> create(ScriptExecutionContext*, ThreadableLoaderClient*, const ResourceRequest&, const ThreadableLoaderOptions&);
    7278
    7379        virtual void cancel() = 0;
  • trunk/WebCore/loader/WorkerThreadableLoader.cpp

    r44737 r47291  
    5454static const char loadResourceSynchronouslyMode[] = "loadResourceSynchronouslyMode";
    5555
    56 WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting,
    57                                                ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
     56WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options)
    5857    : m_workerContext(workerContext)
    5958    , m_workerClientWrapper(ThreadableLoaderClientWrapper::create(client))
    60     , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy)))
     59    , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, options)))
    6160{
    6261}
     
    6766}
    6867
    69 void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
     68void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
    7069{
    7170    WorkerRunLoop& runLoop = workerContext->thread()->runLoop();
     
    7574    mode.append(String::number(runLoop.createUniqueId()));
    7675
    77     ContentSniff contentSniff = request.url().isLocalFile() ? SniffContent : DoNotSniffContent;
    78     RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerContext, &client, mode, request, DoNotSendLoadCallbacks, contentSniff, storedCredentials, crossOriginRedirectPolicy);
    79 
     76    RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerContext, &client, mode, request, options);
    8077    MessageQueueWaitResult result = MessageQueueMessageReceived;
    8178    while (!loader->done() && result != MessageQueueTerminated)
     
    9289
    9390WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, WorkerLoaderProxy& loaderProxy, const String& taskMode,
    94                                                            const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials,
    95                                                            CrossOriginRedirectPolicy crossOriginRedirectPolicy)
     91                                                           const ResourceRequest& request, const ThreadableLoaderOptions& options)
    9692    : m_workerClientWrapper(workerClientWrapper)
    9793    , m_loaderProxy(loaderProxy)
     
    9995{
    10096    ASSERT(m_workerClientWrapper.get());
    101     m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
     97    m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, options));
    10298}
    10399
     
    106102}
    107103
    108 void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
     104void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, ThreadableLoaderOptions options)
    109105{
    110106    ASSERT(isMainThread());
     
    118114    // will return a 0 value.  Either this should return 0 or the other code path should do a callback with
    119115    // a failure.
    120     thisPtr->m_mainThreadLoader = ThreadableLoader::create(context, thisPtr, *request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy);
     116    thisPtr->m_mainThreadLoader = ThreadableLoader::create(context, thisPtr, *request, options);
    121117    ASSERT(thisPtr->m_mainThreadLoader);
    122118}
  • trunk/WebCore/loader/WorkerThreadableLoader.h

    r44737 r47291  
    5656    class WorkerThreadableLoader : public RefCounted<WorkerThreadableLoader>, public ThreadableLoader {
    5757    public:
    58         static void loadResourceSynchronously(WorkerContext*, const ResourceRequest&, ThreadableLoaderClient&, StoredCredentials, CrossOriginRedirectPolicy);
    59         static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
     58        static void loadResourceSynchronously(WorkerContext*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
     59        static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options)
    6060        {
    61             return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
     61            return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, options));
    6262        }
    6363
     
    9898        public:
    9999            // All executed on the worker context's thread.
    100             MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
     100            MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&);
    101101            void cancel();
    102102            void destroy();
     
    110110            ~MainThreadBridge();
    111111
    112             static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, std::auto_ptr<CrossThreadResourceRequestData>, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
     112            static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, std::auto_ptr<CrossThreadResourceRequestData>, ThreadableLoaderOptions);
    113113            static void mainThreadCancel(ScriptExecutionContext*, MainThreadBridge*);
    114114            virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
     
    134134        };
    135135
    136         WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
     136        WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&);
    137137
    138138        RefPtr<WorkerContext> m_workerContext;
  • trunk/WebCore/platform/CrossThreadCopier.h

    r45381 r47291  
    4747    struct CrossThreadResourceResponseData;
    4848    struct CrossThreadResourceRequestData;
     49    struct ThreadableLoaderOptions;
    4950
    5051    template<typename T> struct CrossThreadCopierPassThrough {
     
    6465    // Pointers get passed through without any significant changes.
    6566    template<typename T> struct CrossThreadCopierBase<false, T*> : public CrossThreadCopierPassThrough<T*> {
     67    };
     68
     69    template<> struct CrossThreadCopierBase<false, ThreadableLoaderOptions> : public CrossThreadCopierPassThrough<ThreadableLoaderOptions> {
    6670    };
    6771
  • trunk/WebCore/workers/WorkerScriptLoader.cpp

    r46570 r47291  
    6060
    6161    ASSERT(scriptExecutionContext->isWorkerContext());
    62     WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(scriptExecutionContext), *request, *this, AllowStoredCredentials, crossOriginRedirectPolicy);
     62
     63    ThreadableLoaderOptions options;
     64    options.allowCredentials = true;
     65    options.crossOriginRequestPolicy = AllowCrossOriginRequests;
     66    options.crossOriginRedirectPolicy = crossOriginRedirectPolicy;
     67
     68    WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(scriptExecutionContext), *request, *this, options);
    6369}
    6470   
     
    7379        return;
    7480
    75     m_threadableLoader = ThreadableLoader::create(scriptExecutionContext, this, *request, DoNotSendLoadCallbacks, DoNotSniffContent, AllowStoredCredentials, crossOriginRedirectPolicy);
     81    ThreadableLoaderOptions options;
     82    options.allowCredentials = true;
     83    options.crossOriginRequestPolicy = AllowCrossOriginRequests;
     84    options.crossOriginRedirectPolicy = crossOriginRedirectPolicy;
     85
     86    m_threadableLoader = ThreadableLoader::create(scriptExecutionContext, this, *request, options);
    7687}
    7788
  • trunk/WebCore/xml/XMLHttpRequest.cpp

    r45786 r47291  
    2626#include "CString.h"
    2727#include "CrossOriginAccessControl.h"
    28 #include "CrossOriginPreflightResultCache.h"
    2928#include "DOMImplementation.h"
    3029#include "Document.h"
     
    9493    for (unsigned i = 0; i < length; i++) {
    9594        UChar c = name[i];
    96        
     95
    9796        if (c >= 127 || c <= 32)
    9897            return false;
    99        
     98
    10099        if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
    101100            c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
     
    104103            return false;
    105104    }
    106    
     105
    107106    return true;
    108107}
    109    
     108
    110109static bool isValidHeaderValue(const String& name)
    111110{
    112     // FIXME: This should really match name against 
     111    // FIXME: This should really match name against
    113112    // field-value in section 4.2 of RFC 2616.
    114        
     113
    115114    return !name.contains('\r') && !name.contains('\n');
    116115}
     
    144143    , m_createdDocument(false)
    145144    , m_error(false)
     145    , m_uploadEventsAllowed(true)
    146146    , m_uploadComplete(false)
    147147    , m_sameOriginRequest(true)
    148     , m_inPreflight(false)
    149148    , m_didTellLoaderAboutRequest(false)
    150149    , m_receivedLength(0)
     
    208207            m_responseXML->finishParsing();
    209208            m_responseXML->close();
    210            
     209
    211210            if (!m_responseXML->wellFormed())
    212211                m_responseXML = 0;
     
    237236            if (*listenerIter == eventListener)
    238237                return;
    239        
     238
    240239        listeners.append(eventListener);
    241240        m_eventListeners.add(eventType, listeners);
     
    323322        return;
    324323    }
    325    
     324
    326325    // Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same.
    327326    String methodUpper(method.upper());
    328    
     327
    329328    if (methodUpper == "TRACE" || methodUpper == "TRACK" || methodUpper == "CONNECT") {
    330329        ec = SECURITY_ERR;
     
    336335    if (methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD"
    337336        || methodUpper == "INDEX" || methodUpper == "LOCK" || methodUpper == "M-POST" || methodUpper == "MKCOL" || methodUpper == "MOVE"
    338         || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT" 
     337        || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT"
    339338        || methodUpper == "UNLOCK")
    340339        m_method = methodUpper;
     
    358357    KURL urlWithCredentials(url);
    359358    urlWithCredentials.setUser(user);
    360    
     359
    361360    open(method, urlWithCredentials, async, ec);
    362361}
     
    367366    urlWithCredentials.setUser(user);
    368367    urlWithCredentials.setPass(password);
    369    
     368
    370369    open(method, urlWithCredentials, async, ec);
    371370}
     
    464463void XMLHttpRequest::createRequest(ExceptionCode& ec)
    465464{
    466     // Upload event listeners should be disallowed for simple cross-origin requests, because POSTing to an URL that does not
    467     // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all. If a listener exists
    468     // when creating the request, it will force preflight.
     465    // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
     466    // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
    469467    // Also, only async requests support upload progress events.
    470     m_uploadEventsAllowed = false;
     468    bool forcePreflight = false;
    471469    if (m_async) {
    472470        dispatchLoadStartEvent();
    473471        if (m_requestEntityBody && m_upload) {
    474             m_uploadEventsAllowed = m_upload->hasListeners();
     472            forcePreflight = m_upload->hasListeners();
    475473            m_upload->dispatchLoadStartEvent();
    476474        }
     
    479477    m_sameOriginRequest = scriptExecutionContext()->securityOrigin()->canRequest(m_url);
    480478
    481     if (!m_sameOriginRequest) {
    482         makeCrossOriginAccessRequest(ec);
    483         return;
    484     }
    485 
    486     m_uploadEventsAllowed = true;
    487 
    488     makeSameOriginRequest(ec);
    489 }
    490 
    491 void XMLHttpRequest::makeSameOriginRequest(ExceptionCode& ec)
    492 {
    493     ASSERT(m_sameOriginRequest);
     479    // We also remember whether upload events should be allowed for this request in case the upload listeners are
     480    // added after the request is started.
     481    m_uploadEventsAllowed = !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders);
    494482
    495483    ResourceRequest request(m_url);
     
    505493        request.addHTTPHeaderFields(m_requestHeaders);
    506494
    507     if (m_async)
    508         loadRequestAsynchronously(request);
    509     else
    510         loadRequestSynchronously(request, ec);
    511 }
    512 
    513 void XMLHttpRequest::makeCrossOriginAccessRequest(ExceptionCode& ec)
    514 {
    515     ASSERT(!m_sameOriginRequest);
    516 
    517     if (!m_uploadEventsAllowed && isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders))
    518         makeSimpleCrossOriginAccessRequest(ec);
    519     else
    520         makeCrossOriginAccessRequestWithPreflight(ec);
    521 }
    522 
    523 void XMLHttpRequest::makeSimpleCrossOriginAccessRequest(ExceptionCode& ec)
    524 {
    525     ASSERT(isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders));
    526 
    527     // Cross-origin requests are only defined for HTTP. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied.
    528     if (!m_url.protocolInHTTPFamily()) {
    529         ec = XMLHttpRequestException::NETWORK_ERR;
    530         networkError();
    531         return;
    532     }
    533 
    534     KURL url = m_url;
    535     url.setUser(String());
    536     url.setPass(String());
    537 
    538     ResourceRequest request(url);
    539     request.setHTTPMethod(m_method);
    540     request.setAllowHTTPCookies(m_includeCredentials);
    541     request.setHTTPOrigin(scriptExecutionContext()->securityOrigin()->toString());
    542 
    543     if (m_requestHeaders.size() > 0)
    544         request.addHTTPHeaderFields(m_requestHeaders);
    545 
    546     if (m_requestEntityBody) {
    547         ASSERT(m_method != "GET");
    548         ASSERT(m_method != "HEAD");
    549         request.setHTTPBody(m_requestEntityBody.release());
    550     }
    551 
    552     if (m_async)
    553         loadRequestAsynchronously(request);
    554     else
    555         loadRequestSynchronously(request, ec);
    556 }
    557 
    558 void XMLHttpRequest::makeCrossOriginAccessRequestWithPreflight(ExceptionCode& ec)
    559 {
    560     String origin = scriptExecutionContext()->securityOrigin()->toString();
    561     KURL url = m_url;
    562     url.setUser(String());
    563     url.setPass(String());
    564 
    565     if (!CrossOriginPreflightResultCache::shared().canSkipPreflight(origin, url, m_includeCredentials, m_method, m_requestHeaders)) {
    566         m_inPreflight = true;
    567         ResourceRequest preflightRequest(url);
    568         preflightRequest.setHTTPMethod("OPTIONS");
    569         preflightRequest.setHTTPHeaderField("Origin", origin);
    570         preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", m_method);
    571 
    572         if (m_requestHeaders.size() > 0) {
    573             Vector<UChar> headerBuffer;
    574             HTTPHeaderMap::const_iterator it = m_requestHeaders.begin();
    575             append(headerBuffer, it->first);
    576             ++it;
    577 
    578             HTTPHeaderMap::const_iterator end = m_requestHeaders.end();
    579             for (; it != end; ++it) {
    580                 headerBuffer.append(',');
    581                 headerBuffer.append(' ');
    582                 append(headerBuffer, it->first);
    583             }
    584 
    585             preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer));
    586             preflightRequest.addHTTPHeaderFields(m_requestHeaders);
    587         }
    588 
    589         if (m_async) {
    590             m_uploadEventsAllowed = true;
    591             loadRequestAsynchronously(preflightRequest);
    592             return;
    593         }
    594 
    595         loadRequestSynchronously(preflightRequest, ec);
    596         m_inPreflight = false;
    597 
    598         if (ec)
    599             return;
    600     }
    601 
    602     // Send the actual request.
    603     ResourceRequest request(url);
    604     request.setHTTPMethod(m_method);
    605     request.setAllowHTTPCookies(m_includeCredentials);
    606     request.setHTTPHeaderField("Origin", origin);
    607 
    608     if (m_requestHeaders.size() > 0)
    609         request.addHTTPHeaderFields(m_requestHeaders);
    610 
    611     if (m_requestEntityBody) {
    612         ASSERT(m_method != "GET");
    613         ASSERT(m_method != "HEAD");
    614         request.setHTTPBody(m_requestEntityBody.release());
    615     }
     495    ThreadableLoaderOptions options;
     496    options.sendLoadCallbacks = true;
     497    options.sniffContent = false;
     498    options.forcePreflight = forcePreflight;
     499    options.allowCredentials = m_sameOriginRequest || m_includeCredentials;
     500    options.crossOriginRequestPolicy = UseAccessControl;
     501    options.crossOriginRedirectPolicy = DenyCrossOriginRedirect;
     502
     503    m_exceptionCode = 0;
     504    m_error = false;
    616505
    617506    if (m_async) {
    618         m_uploadEventsAllowed = true;
    619         loadRequestAsynchronously(request);
    620         return;
    621     }
    622 
    623     loadRequestSynchronously(request, ec);
    624 }
    625 
    626 void XMLHttpRequest::handleAsynchronousPreflightResult()
    627 {
    628     ASSERT(m_inPreflight);
    629     ASSERT(m_async);
    630 
    631     m_inPreflight = false;
    632 
    633     KURL url = m_url;
    634     url.setUser(String());
    635     url.setPass(String());
    636 
    637     ResourceRequest request(url);
    638     request.setHTTPMethod(m_method);
    639     request.setAllowHTTPCookies(m_includeCredentials);
    640     request.setHTTPOrigin(scriptExecutionContext()->securityOrigin()->toString());
    641 
    642     if (m_requestHeaders.size() > 0)
    643         request.addHTTPHeaderFields(m_requestHeaders);
    644 
    645     if (m_requestEntityBody) {
    646         ASSERT(m_method != "GET");
    647         ASSERT(m_method != "HEAD");
    648         request.setHTTPBody(m_requestEntityBody.release());
    649     }
    650 
    651     m_uploadEventsAllowed = true;
    652     loadRequestAsynchronously(request);
    653 }
    654 
    655 void XMLHttpRequest::loadRequestSynchronously(ResourceRequest& request, ExceptionCode& ec)
    656 {
    657     ASSERT(!m_async);
    658 
    659     m_loader = 0;
    660     m_exceptionCode = 0;
    661     StoredCredentials storedCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
    662 
    663     ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, storedCredentials);
     507        request.setReportUploadProgress(true);
     508        setPendingActivity(this);
     509        m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options);
     510    } else
     511        ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, options);
     512
    664513    if (!m_exceptionCode && m_error)
    665514        m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
     
    667516}
    668517
    669 void XMLHttpRequest::loadRequestAsynchronously(ResourceRequest& request)
    670 {
    671     ASSERT(m_async);
    672     m_exceptionCode = 0;
    673     // SubresourceLoader::create can return null here, for example if we're no longer attached to a page.
    674     // This is true while running onunload handlers.
    675     // FIXME: We need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
    676     // FIXME: Maybe create can return null for other reasons too?
    677     LoadCallbacks callbacks = m_inPreflight ? DoNotSendLoadCallbacks : SendLoadCallbacks;
    678     StoredCredentials storedCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
    679 
    680     if (m_upload)
    681         request.setReportUploadProgress(true);
    682 
    683     m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, callbacks, DoNotSniffContent, storedCredentials, DenyCrossOriginRedirect);
    684 
    685     if (m_loader) {
    686         // Neither this object nor the JavaScript wrapper should be deleted while
    687         // a request is in progress because we need to keep the listeners alive,
    688         // and they are referenced by the JavaScript wrapper.
    689         setPendingActivity(this);
    690        
    691         // For now we should only balance the nonCached request count for main-thread XHRs and not
    692         // Worker XHRs, as the Cache is not thread-safe.
    693         // This will become irrelevant after https://bugs.webkit.org/show_bug.cgi?id=27165 is resolved.
    694         if (!scriptExecutionContext()->isWorkerContext()) {
    695             ASSERT(isMainThread());
    696             ASSERT(!m_didTellLoaderAboutRequest);
    697             cache()->loader()->nonCacheRequestInFlight(m_url);
    698             m_didTellLoaderAboutRequest = true;
    699         }
    700     }
    701 }
    702 
    703518void XMLHttpRequest::abort()
    704519{
     
    712527    // Clear headers as required by the spec
    713528    m_requestHeaders.clear();
    714    
     529
    715530    if ((m_state <= OPENED && !sendFlag) || m_state == DONE)
    716531        m_state = UNSENT;
     
    795610}
    796611
    797 void XMLHttpRequest::dropProtection()       
     612void XMLHttpRequest::dropProtection()
    798613{
    799614#if USE(JSC)
     
    855670void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const String& value)
    856671{
    857     pair<HTTPHeaderMap::iterator, bool> result = m_requestHeaders.add(name, value); 
     672    pair<HTTPHeaderMap::iterator, bool> result = m_requestHeaders.add(name, value);
    858673    if (!result.second)
    859674        result.first->second += ", " + value;
     
    940755    if (mimeType.isEmpty())
    941756        mimeType = "text/xml";
    942    
     757
    943758    return mimeType;
    944759}
     
    982797        m_didTellLoaderAboutRequest = false;
    983798    }
    984    
     799
    985800    // If we are already in an error state, for instance we called abort(), bail out early.
    986801    if (m_error)
     
    1012827        return;
    1013828
    1014     if (m_inPreflight) {
    1015         didFinishLoadingPreflight();
    1016         return;
    1017     }
    1018 
    1019829    if (m_state < HEADERS_RECEIVED)
    1020830        changeState(HEADERS_RECEIVED);
     
    1034844    if (hadLoader)
    1035845        dropProtection();
    1036 }
    1037 
    1038 void XMLHttpRequest::didFinishLoadingPreflight()
    1039 {
    1040     ASSERT(m_inPreflight);
    1041     ASSERT(!m_sameOriginRequest);
    1042 
    1043     // FIXME: this can probably be moved to didReceiveResponsePreflight.
    1044     if (m_async)
    1045         handleAsynchronousPreflightResult();
    1046 
    1047     if (m_loader)
    1048         unsetPendingActivity(this);
    1049846}
    1050847
     
    1066863void XMLHttpRequest::didReceiveResponse(const ResourceResponse& response)
    1067864{
    1068     if (m_inPreflight) {
    1069         didReceiveResponsePreflight(response);
    1070         return;
    1071     }
    1072 
    1073     if (!m_sameOriginRequest) {
    1074         if (!passesAccessControlCheck(response, m_includeCredentials, scriptExecutionContext()->securityOrigin())) {
    1075             networkError();
    1076             return;
    1077         }
    1078     }
    1079 
    1080865    m_response = response;
    1081866    m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride);
     
    1084869}
    1085870
    1086 void XMLHttpRequest::didReceiveResponsePreflight(const ResourceResponse& response)
    1087 {
    1088     ASSERT(m_inPreflight);
    1089     ASSERT(!m_sameOriginRequest);
    1090 
    1091     if (!passesAccessControlCheck(response, m_includeCredentials, scriptExecutionContext()->securityOrigin())) {
    1092         networkError();
    1093         return;
    1094     }
    1095 
    1096     OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult(new CrossOriginPreflightResultCacheItem(m_includeCredentials));
    1097     if (!preflightResult->parse(response)
    1098         || !preflightResult->allowsCrossOriginMethod(m_method)
    1099         || !preflightResult->allowsCrossOriginHeaders(m_requestHeaders)) {
    1100         networkError();
    1101         return;
    1102     }
    1103 
    1104     CrossOriginPreflightResultCache::shared().appendEntry(scriptExecutionContext()->securityOrigin()->toString(), m_url, preflightResult.release());
    1105 }
    1106 
    1107871void XMLHttpRequest::didReceiveAuthenticationCancellation(const ResourceResponse& failureResponse)
    1108872{
     
    1112876void XMLHttpRequest::didReceiveData(const char* data, int len)
    1113877{
    1114     if (m_inPreflight || m_error)
     878    if (m_error)
    1115879        return;
    1116880
    1117881    if (m_state < HEADERS_RECEIVED)
    1118882        changeState(HEADERS_RECEIVED);
    1119  
     883
    1120884    if (!m_decoder) {
    1121885        if (!m_responseEncoding.isEmpty())
     
    1211975void XMLHttpRequest::dispatchProgressEvent(long long expectedLength)
    1212976{
    1213     dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength, 
     977    dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength,
    1214978                                        static_cast<unsigned>(m_receivedLength), static_cast<unsigned>(expectedLength));
    1215979}
     
    12361000}
    12371001
    1238 } // namespace WebCore 
     1002} // namespace WebCore
  • trunk/WebCore/xml/XMLHttpRequest.h

    r45732 r47291  
    118118private:
    119119    XMLHttpRequest(ScriptExecutionContext*);
    120    
     120
    121121    virtual void refEventTarget() { ref(); }
    122122    virtual void derefEventTarget() { deref(); }
     
    136136    virtual void didReceiveAuthenticationCancellation(const ResourceResponse&);
    137137
    138     // Special versions for the preflight
    139     void didReceiveResponsePreflight(const ResourceResponse&);
    140     void didFinishLoadingPreflight();
    141 
    142138    void updateAndDispatchOnProgress(unsigned int len);
    143139
     
    159155
    160156    void createRequest(ExceptionCode&);
    161 
    162     void makeSameOriginRequest(ExceptionCode&);
    163     void makeCrossOriginAccessRequest(ExceptionCode&);
    164 
    165     void makeSimpleCrossOriginAccessRequest(ExceptionCode&);
    166     void makeCrossOriginAccessRequestWithPreflight(ExceptionCode&);
    167     void handleAsynchronousPreflightResult();
    168 
    169     void loadRequestSynchronously(ResourceRequest&, ExceptionCode&);
    170     void loadRequestAsynchronously(ResourceRequest&);
    171157
    172158    void genericError();
     
    224210
    225211    bool m_sameOriginRequest;
    226     bool m_allowAccess;
    227     bool m_inPreflight;
    228212    bool m_didTellLoaderAboutRequest;
    229213
    230214    // Used for onprogress tracking
    231215    long long m_receivedLength;
    232    
     216
    233217    unsigned m_lastSendLineNumber;
    234218    String m_lastSendURL;
Note: See TracChangeset for help on using the changeset viewer.