Changeset 47291 in webkit
- Timestamp:
- Aug 14, 2009 12:25:37 PM (15 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r47288 r47291 1 2009-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 1 52 2009-08-14 Darin Adler <darin@apple.com> 2 53 -
trunk/WebCore/loader/DocumentThreadableLoader.cpp
r45935 r47291 33 33 34 34 #include "AuthenticationChallenge.h" 35 #include "CrossOriginAccessControl.h" 36 #include "CrossOriginPreflightResultCache.h" 35 37 #include "Document.h" 36 #include "DocumentThreadableLoader.h"37 38 #include "Frame.h" 38 39 #include "FrameLoader.h" … … 44 45 namespace WebCore { 45 46 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)); 47 void 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 54 PassRefPtr<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)); 84 57 if (!loader->m_loader) 85 58 loader = 0; … … 87 60 } 88 61 89 DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)62 DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options) 90 63 : m_client(client) 91 64 , m_document(document) 92 , m_ allowStoredCredentials(storedCredentials == AllowStoredCredentials)65 , m_options(options) 93 66 , m_sameOriginRequest(document->securityOrigin()->canRequest(request.url())) 94 , m_ denyCrossOriginRedirect(crossOriginRedirectPolicy == DenyCrossOriginRedirect)67 , m_async(blockingBehavior == LoadAsynchronously) 95 68 { 96 69 ASSERT(document); 97 70 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 98 void 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 118 void 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); 101 148 } 102 149 … … 124 171 125 172 // 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())) { 127 174 RefPtr<DocumentThreadableLoader> protect(this); 128 175 m_client->didFailRedirectCheck(); … … 144 191 ASSERT_UNUSED(loader, loader == m_loader); 145 192 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 } 147 218 } 148 219 … … 159 230 ASSERT(loader == m_loader); 160 231 ASSERT(m_client); 161 m_client->didFinishLoading(loader->identifier()); 232 didFinishLoading(loader->identifier()); 233 } 234 235 void 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); 162 243 } 163 244 … … 175 256 ASSERT_UNUSED(loader, loader == m_loader); 176 257 177 if (!m_ allowStoredCredentials) {258 if (!m_options.allowCredentials) { 178 259 shouldUseCredentialStorage = false; 179 260 return true; … … 201 282 } 202 283 284 void 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 293 void DocumentThreadableLoader::preflightFailure() 294 { 295 m_client->didFail(ResourceError()); 296 } 297 298 void 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 203 341 } // namespace WebCore -
trunk/WebCore/loader/DocumentThreadableLoader.h
r44737 r47291 34 34 #include "SubresourceLoaderClient.h" 35 35 #include "ThreadableLoader.h" 36 #include <wtf/OwnPtr.h> 36 37 #include <wtf/PassRefPtr.h> 37 38 #include <wtf/RefCounted.h> … … 45 46 class DocumentThreadableLoader : public RefCounted<DocumentThreadableLoader>, public ThreadableLoader, private SubresourceLoaderClient { 46 47 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&); 49 50 virtual ~DocumentThreadableLoader(); 50 51 … … 59 60 60 61 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 62 69 virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse); 63 70 virtual void didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent); … … 72 79 virtual void receivedCancellation(SubresourceLoader*, const AuthenticationChallenge&); 73 80 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 74 89 RefPtr<SubresourceLoader> m_loader; 75 90 ThreadableLoaderClient* m_client; 76 91 Document* m_document; 77 bool m_allowStoredCredentials;92 ThreadableLoaderOptions m_options; 78 93 bool m_sameOriginRequest; 79 bool m_denyCrossOriginRedirect; 94 bool m_async; 95 OwnPtr<ResourceRequest> m_actualRequest; // non-null during Access Control preflight checks 80 96 }; 81 97 -
trunk/WebCore/loader/ThreadableLoader.cpp
r44737 r47291 41 41 namespace WebCore { 42 42 43 PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)43 PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options) 44 44 { 45 45 ASSERT(client); … … 48 48 #if ENABLE(WORKERS) 49 49 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); 51 51 #endif // ENABLE(WORKERS) 52 52 53 53 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); 55 55 } 56 56 57 void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials)57 void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options) 58 58 { 59 59 ASSERT(context); … … 61 61 #if ENABLE(WORKERS) 62 62 if (context->isWorkerContext()) { 63 WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, storedCredentials, DenyCrossOriginRedirect);63 WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, options); 64 64 return; 65 65 } … … 67 67 68 68 ASSERT(context->isDocument()); 69 DocumentThreadableLoader::loadResourceSynchronously(static_cast<Document*>(context), request, client, storedCredentials);69 DocumentThreadableLoader::loadResourceSynchronously(static_cast<Document*>(context), request, client, options); 70 70 } 71 71 -
trunk/WebCore/loader/ThreadableLoader.h
r45891 r47291 44 44 class ThreadableLoaderClient; 45 45 46 enum LoadCallbacks {47 SendLoadCallbacks,48 DoNotSendLoadCallbacks49 };50 51 enum ContentSniff {52 SniffContent,53 DoNotSniffContent54 };55 56 46 enum StoredCredentials { 57 47 AllowStoredCredentials, 58 48 DoNotAllowStoredCredentials 59 49 }; 60 50 51 enum CrossOriginRequestPolicy { 52 DenyCrossOriginRequests, 53 UseAccessControl, 54 AllowCrossOriginRequests 55 }; 56 61 57 enum CrossOriginRedirectPolicy { 62 58 DenyCrossOriginRedirect, 63 59 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; 64 70 }; 65 71 … … 68 74 class ThreadableLoader : public Noncopyable { 69 75 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&); 72 78 73 79 virtual void cancel() = 0; -
trunk/WebCore/loader/WorkerThreadableLoader.cpp
r44737 r47291 54 54 static const char loadResourceSynchronouslyMode[] = "loadResourceSynchronouslyMode"; 55 55 56 WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting, 57 ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy) 56 WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options) 58 57 : m_workerContext(workerContext) 59 58 , 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))) 61 60 { 62 61 } … … 67 66 } 68 67 69 void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)68 void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options) 70 69 { 71 70 WorkerRunLoop& runLoop = workerContext->thread()->runLoop(); … … 75 74 mode.append(String::number(runLoop.createUniqueId())); 76 75 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); 80 77 MessageQueueWaitResult result = MessageQueueMessageReceived; 81 78 while (!loader->done() && result != MessageQueueTerminated) … … 92 89 93 90 WorkerThreadableLoader::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) 96 92 : m_workerClientWrapper(workerClientWrapper) 97 93 , m_loaderProxy(loaderProxy) … … 99 95 { 100 96 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)); 102 98 } 103 99 … … 106 102 } 107 103 108 void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)104 void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, ThreadableLoaderOptions options) 109 105 { 110 106 ASSERT(isMainThread()); … … 118 114 // will return a 0 value. Either this should return 0 or the other code path should do a callback with 119 115 // 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); 121 117 ASSERT(thisPtr->m_mainThreadLoader); 122 118 } -
trunk/WebCore/loader/WorkerThreadableLoader.h
r44737 r47291 56 56 class WorkerThreadableLoader : public RefCounted<WorkerThreadableLoader>, public ThreadableLoader { 57 57 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) 60 60 { 61 return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));61 return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, options)); 62 62 } 63 63 … … 98 98 public: 99 99 // 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&); 101 101 void cancel(); 102 102 void destroy(); … … 110 110 ~MainThreadBridge(); 111 111 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); 113 113 static void mainThreadCancel(ScriptExecutionContext*, MainThreadBridge*); 114 114 virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent); … … 134 134 }; 135 135 136 WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);136 WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&); 137 137 138 138 RefPtr<WorkerContext> m_workerContext; -
trunk/WebCore/platform/CrossThreadCopier.h
r45381 r47291 47 47 struct CrossThreadResourceResponseData; 48 48 struct CrossThreadResourceRequestData; 49 struct ThreadableLoaderOptions; 49 50 50 51 template<typename T> struct CrossThreadCopierPassThrough { … … 64 65 // Pointers get passed through without any significant changes. 65 66 template<typename T> struct CrossThreadCopierBase<false, T*> : public CrossThreadCopierPassThrough<T*> { 67 }; 68 69 template<> struct CrossThreadCopierBase<false, ThreadableLoaderOptions> : public CrossThreadCopierPassThrough<ThreadableLoaderOptions> { 66 70 }; 67 71 -
trunk/WebCore/workers/WorkerScriptLoader.cpp
r46570 r47291 60 60 61 61 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); 63 69 } 64 70 … … 73 79 return; 74 80 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); 76 87 } 77 88 -
trunk/WebCore/xml/XMLHttpRequest.cpp
r45786 r47291 26 26 #include "CString.h" 27 27 #include "CrossOriginAccessControl.h" 28 #include "CrossOriginPreflightResultCache.h"29 28 #include "DOMImplementation.h" 30 29 #include "Document.h" … … 94 93 for (unsigned i = 0; i < length; i++) { 95 94 UChar c = name[i]; 96 95 97 96 if (c >= 127 || c <= 32) 98 97 return false; 99 98 100 99 if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' || 101 100 c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' || … … 104 103 return false; 105 104 } 106 105 107 106 return true; 108 107 } 109 108 110 109 static bool isValidHeaderValue(const String& name) 111 110 { 112 // FIXME: This should really match name against 111 // FIXME: This should really match name against 113 112 // field-value in section 4.2 of RFC 2616. 114 113 115 114 return !name.contains('\r') && !name.contains('\n'); 116 115 } … … 144 143 , m_createdDocument(false) 145 144 , m_error(false) 145 , m_uploadEventsAllowed(true) 146 146 , m_uploadComplete(false) 147 147 , m_sameOriginRequest(true) 148 , m_inPreflight(false)149 148 , m_didTellLoaderAboutRequest(false) 150 149 , m_receivedLength(0) … … 208 207 m_responseXML->finishParsing(); 209 208 m_responseXML->close(); 210 209 211 210 if (!m_responseXML->wellFormed()) 212 211 m_responseXML = 0; … … 237 236 if (*listenerIter == eventListener) 238 237 return; 239 238 240 239 listeners.append(eventListener); 241 240 m_eventListeners.add(eventType, listeners); … … 323 322 return; 324 323 } 325 324 326 325 // Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same. 327 326 String methodUpper(method.upper()); 328 327 329 328 if (methodUpper == "TRACE" || methodUpper == "TRACK" || methodUpper == "CONNECT") { 330 329 ec = SECURITY_ERR; … … 336 335 if (methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD" 337 336 || 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" 339 338 || methodUpper == "UNLOCK") 340 339 m_method = methodUpper; … … 358 357 KURL urlWithCredentials(url); 359 358 urlWithCredentials.setUser(user); 360 359 361 360 open(method, urlWithCredentials, async, ec); 362 361 } … … 367 366 urlWithCredentials.setUser(user); 368 367 urlWithCredentials.setPass(password); 369 368 370 369 open(method, urlWithCredentials, async, ec); 371 370 } … … 464 463 void XMLHttpRequest::createRequest(ExceptionCode& ec) 465 464 { 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. 469 467 // Also, only async requests support upload progress events. 470 m_uploadEventsAllowed= false;468 bool forcePreflight = false; 471 469 if (m_async) { 472 470 dispatchLoadStartEvent(); 473 471 if (m_requestEntityBody && m_upload) { 474 m_uploadEventsAllowed= m_upload->hasListeners();472 forcePreflight = m_upload->hasListeners(); 475 473 m_upload->dispatchLoadStartEvent(); 476 474 } … … 479 477 m_sameOriginRequest = scriptExecutionContext()->securityOrigin()->canRequest(m_url); 480 478 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); 494 482 495 483 ResourceRequest request(m_url); … … 505 493 request.addHTTPHeaderFields(m_requestHeaders); 506 494 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; 616 505 617 506 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 664 513 if (!m_exceptionCode && m_error) 665 514 m_exceptionCode = XMLHttpRequestException::NETWORK_ERR; … … 667 516 } 668 517 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 while687 // 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 not692 // 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 703 518 void XMLHttpRequest::abort() 704 519 { … … 712 527 // Clear headers as required by the spec 713 528 m_requestHeaders.clear(); 714 529 715 530 if ((m_state <= OPENED && !sendFlag) || m_state == DONE) 716 531 m_state = UNSENT; … … 795 610 } 796 611 797 void XMLHttpRequest::dropProtection() 612 void XMLHttpRequest::dropProtection() 798 613 { 799 614 #if USE(JSC) … … 855 670 void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const String& value) 856 671 { 857 pair<HTTPHeaderMap::iterator, bool> result = m_requestHeaders.add(name, value); 672 pair<HTTPHeaderMap::iterator, bool> result = m_requestHeaders.add(name, value); 858 673 if (!result.second) 859 674 result.first->second += ", " + value; … … 940 755 if (mimeType.isEmpty()) 941 756 mimeType = "text/xml"; 942 757 943 758 return mimeType; 944 759 } … … 982 797 m_didTellLoaderAboutRequest = false; 983 798 } 984 799 985 800 // If we are already in an error state, for instance we called abort(), bail out early. 986 801 if (m_error) … … 1012 827 return; 1013 828 1014 if (m_inPreflight) {1015 didFinishLoadingPreflight();1016 return;1017 }1018 1019 829 if (m_state < HEADERS_RECEIVED) 1020 830 changeState(HEADERS_RECEIVED); … … 1034 844 if (hadLoader) 1035 845 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);1049 846 } 1050 847 … … 1066 863 void XMLHttpRequest::didReceiveResponse(const ResourceResponse& response) 1067 864 { 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 1080 865 m_response = response; 1081 866 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); … … 1084 869 } 1085 870 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 1107 871 void XMLHttpRequest::didReceiveAuthenticationCancellation(const ResourceResponse& failureResponse) 1108 872 { … … 1112 876 void XMLHttpRequest::didReceiveData(const char* data, int len) 1113 877 { 1114 if (m_ inPreflight || m_error)878 if (m_error) 1115 879 return; 1116 880 1117 881 if (m_state < HEADERS_RECEIVED) 1118 882 changeState(HEADERS_RECEIVED); 1119 883 1120 884 if (!m_decoder) { 1121 885 if (!m_responseEncoding.isEmpty()) … … 1211 975 void XMLHttpRequest::dispatchProgressEvent(long long expectedLength) 1212 976 { 1213 dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength, 977 dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength, 1214 978 static_cast<unsigned>(m_receivedLength), static_cast<unsigned>(expectedLength)); 1215 979 } … … 1236 1000 } 1237 1001 1238 } // namespace WebCore 1002 } // namespace WebCore -
trunk/WebCore/xml/XMLHttpRequest.h
r45732 r47291 118 118 private: 119 119 XMLHttpRequest(ScriptExecutionContext*); 120 120 121 121 virtual void refEventTarget() { ref(); } 122 122 virtual void derefEventTarget() { deref(); } … … 136 136 virtual void didReceiveAuthenticationCancellation(const ResourceResponse&); 137 137 138 // Special versions for the preflight139 void didReceiveResponsePreflight(const ResourceResponse&);140 void didFinishLoadingPreflight();141 142 138 void updateAndDispatchOnProgress(unsigned int len); 143 139 … … 159 155 160 156 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&);171 157 172 158 void genericError(); … … 224 210 225 211 bool m_sameOriginRequest; 226 bool m_allowAccess;227 bool m_inPreflight;228 212 bool m_didTellLoaderAboutRequest; 229 213 230 214 // Used for onprogress tracking 231 215 long long m_receivedLength; 232 216 233 217 unsigned m_lastSendLineNumber; 234 218 String m_lastSendURL;
Note: See TracChangeset
for help on using the changeset viewer.