Reviewed by Adam Barth.
Support cross-origin XMLHttpRequest in isolated worlds
https://bugs.webkit.org/show_bug.cgi?id=59843
Add test for doing a cross-origin XHR in an isolated world via
setIsolatedWorldSecurityOrigin and addOriginAccessWhitelistEntry.
Skipped on JSC ports.
* http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt: Added.
* http/tests/security/isolatedWorld/cross-origin-xhr.html: Added.
* http/tests/security/isolatedWorld/resources/cross-origin-xhr.txt: Added.
* platform/gtk/Skipped:
* platform/mac/Skipped:
* platform/qt/Skipped:
* platform/win/Skipped:
2011-05-26 Mihai Parparita <mihaip@chromium.org>
Reviewed by Adam Barth.
Support cross-origin XMLHttpRequest in isolated worlds
https://bugs.webkit.org/show_bug.cgi?id=59843
Allows isolated worlds to be associated with a different SecurityOrigin
(exposed as a setIsolatedWorldSecurityOrigin function in
ScriptController).
The XMLHttpRequest constructor can then check that it's being
instantiated in an isolated world and use its security origin.
XMLHttpRequest, ThreadableLoader and DocumentThreadableLoader had to be
changed to use the copied SecurityOrigin instead of always grabbing the
Document's.
Test: http/tests/security/isolatedWorld/cross-origin-xhr.html
* bindings/v8/ScriptController.cpp:
(WebCore::ScriptController::setIsolatedWorldSecurityOrigin):
* bindings/v8/ScriptController.h:
* bindings/v8/V8IsolatedContext.cpp:
(WebCore::V8IsolatedContext::setSecurityOrigin):
* bindings/v8/V8IsolatedContext.h:
(WebCore::V8IsolatedContext::securityOrigin):
* bindings/v8/V8Proxy.cpp:
(WebCore::V8Proxy::evaluateInIsolatedWorld):
(WebCore::V8Proxy::setIsolatedWorldSecurityOrigin):
(WebCore::V8Proxy::resetIsolatedWorlds):
* bindings/v8/V8Proxy.h:
* bindings/v8/custom/V8XMLHttpRequestConstructor.cpp:
(WebCore::V8XMLHttpRequest::constructorCallback):
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
(WebCore::DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight):
(WebCore::DocumentThreadableLoader::didReceiveResponse):
(WebCore::DocumentThreadableLoader::preflightSuccess):
(WebCore::DocumentThreadableLoader::isAllowedRedirect):
(WebCore::DocumentThreadableLoader::securityOrigin):
* loader/DocumentThreadableLoader.h:
* loader/ThreadableLoader.h:
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::create):
(WebCore::XMLHttpRequest::XMLHttpRequest):
(WebCore::XMLHttpRequest::securityOrigin):
(WebCore::XMLHttpRequest::responseXML):
(WebCore::XMLHttpRequest::createRequest):
(WebCore::XMLHttpRequest::setRequestHeader):
(WebCore::XMLHttpRequest::getAllResponseHeaders):
(WebCore::XMLHttpRequest::getResponseHeader):
* xml/XMLHttpRequest.h:
2011-05-26 Mihai Parparita <mihaip@chromium.org>
Reviewed by Adam Barth.
Support cross-origin XMLHttpRequest in isolated worlds
https://bugs.webkit.org/show_bug.cgi?id=59843
Expose setIsolatedWorldSecurityOrigin in the WebFrame API.
* public/WebFrame.h:
* src/WebFrameImpl.cpp:
(WebKit::WebFrameImpl::setIsolatedWorldSecurityOrigin):
* src/WebFrameImpl.h:
2011-05-26 Mihai Parparita <mihaip@chromium.org>
Reviewed by Adam Barth.
Support cross-origin XMLHttpRequest in isolated worlds
https://bugs.webkit.org/show_bug.cgi?id=59843
Expose setIsolatedWorldSecurityOrigin in LayoutTestController.
* DumpRenderTree/chromium/LayoutTestController.cpp:
(LayoutTestController::LayoutTestController):
(LayoutTestController::setIsolatedWorldSecurityOrigin):
* DumpRenderTree/chromium/LayoutTestController.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@87423
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2011-05-26 Mihai Parparita <mihaip@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Support cross-origin XMLHttpRequest in isolated worlds
+ https://bugs.webkit.org/show_bug.cgi?id=59843
+
+ Add test for doing a cross-origin XHR in an isolated world via
+ setIsolatedWorldSecurityOrigin and addOriginAccessWhitelistEntry.
+
+ Skipped on JSC ports.
+
+ * http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt: Added.
+ * http/tests/security/isolatedWorld/cross-origin-xhr.html: Added.
+ * http/tests/security/isolatedWorld/resources/cross-origin-xhr.txt: Added.
+ * platform/gtk/Skipped:
+ * platform/mac/Skipped:
+ * platform/qt/Skipped:
+ * platform/win/Skipped:
+
2011-05-26 Adam Klein <adamk@chromium.org>
Unreviewed. Suppress more flaky Linux tests.
--- /dev/null
+CONSOLE MESSAGE: line 1: XMLHttpRequest cannot load http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt. Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
+CONSOLE MESSAGE: line 1: XMLHttpRequest cannot load http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt. Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
+CONSOLE MESSAGE: line 1: XMLHttpRequest cannot load http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt. Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
+Tests that isolated worlds can have XHRs run in a different origin.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+XHR from main world
+XHR completed with status 0
+XHR from isolated world with unchanged security origin
+XHR completed with status 0
+XHR from isolated world with same security origin as XHR target
+XHR completed with status 200
+XHR from isolated world with security origin that is whitelisted for XHR target
+XHR completed with status 200
+XHR from main world is not affected by the isolated world origin or whitelist
+XHR completed with status 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<html>
+<link rel="stylesheet" href="../../js-test-resources/js-test-style.css">
+<script src="../../js-test-resources/js-test-pre.js"></script>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+description('Tests that isolated worlds can have XHRs run in a different origin.');
+
+jsTestIsAsync = true;
+
+var tests = [
+ function() {
+ debug('XHR from main world');
+ xhr();
+ },
+ function() {
+ debug('XHR from isolated world with unchanged security origin');
+ runTestInWorld(1, 'xhr');
+ },
+ function() {
+ debug('XHR from isolated world with same security origin as XHR target');
+ layoutTestController.setIsolatedWorldSecurityOrigin(1, 'http://localhost:8000');
+ runTestInWorld(1, 'xhr');
+ },
+ function() {
+ debug('XHR from isolated world with security origin that is whitelisted for XHR target');
+ layoutTestController.setIsolatedWorldSecurityOrigin(2, 'chrome-extension://123');
+ layoutTestController.addOriginAccessWhitelistEntry('chrome-extension://123', 'http', 'localhost', false);
+ runTestInWorld(2, 'xhr');
+ },
+ function() {
+ debug('XHR from main world is not affected by the isolated world origin or whitelist');
+ xhr();
+ }
+];
+var currentTest = 0;
+
+// This test is meaningless without layoutTestController.
+if (window.layoutTestController) {
+ window.addEventListener(
+ 'message',
+ function(event) {
+ var message = JSON.parse(event.data);
+ switch (message.type) {
+ case 'test-done':
+ currentTest++;
+ if (currentTest == tests.length)
+ finishJSTest();
+ else
+ tests[currentTest]();
+ break;
+ case 'debug':
+ debug(message.message);
+ break;
+ default:
+ testFailed('Unknown message: ' + event.data);
+ break;
+ }
+ },
+ false);
+
+ tests[0]();
+} else {
+ testFailed('Test depends on LayoutTestController and must be run by DRT');
+}
+
+function runTestInWorld(worldId, funcName)
+{
+ layoutTestController.evaluateScriptInIsolatedWorld(
+ worldId, String(eval(funcName)) + "\n" + funcName + "();");
+}
+
+function xhr()
+{
+ function debug(message) {
+ window.postMessage(JSON.stringify({
+ 'type': 'debug',
+ 'message': message
+ }),
+ '*');
+ }
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'http://localhost:8000/security/isolatedWorld/resources/cross-origin-xhr.txt', true);
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState != 4)
+ return;
+
+ debug('XHR completed with status ' + xhr.status);
+ window.postMessage(JSON.stringify({'type': 'test-done'}), '*');
+ };
+ xhr.send(null);
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js-test-resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+Test file for cross-origin XMLHttpRequest tests.
# https://bugs.webkit.org/show_bug.cgi?id=61523
http/tests/eventsource/workers/eventsource-simple.html
+
+# JSC does not support setIsolatedWorldSecurityOrigin (http://webkit.org/b/61540)
+http/tests/security/isolatedWorld/cross-origin-xhr.html
# Fails after r87328:
# https://bugs.webkit.org/show_bug.cgi?id=61487
http/tests/media/video-cross-site.html
+
+# JSC does not support setIsolatedWorldSecurityOrigin (http://webkit.org/b/61540)
+http/tests/security/isolatedWorld/cross-origin-xhr.html
# https://bugs.webkit.org/show_bug.cgi?id=61322
fast/events/selectstart-by-double-triple-clicks.html
fast/events/selectstart-by-drag.html
+
+# JSC does not support setIsolatedWorldSecurityOrigin (http://webkit.org/b/61540)
+http/tests/security/isolatedWorld/cross-origin-xhr.html
# Unskip after implementing LayoutTestController::setDefersLoading and ::goBack.
loader/navigation-while-deferring-loads.html
+
+# JSC does not support setIsolatedWorldSecurityOrigin (http://webkit.org/b/61540)
+http/tests/security/isolatedWorld/cross-origin-xhr.html
+2011-05-26 Mihai Parparita <mihaip@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Support cross-origin XMLHttpRequest in isolated worlds
+ https://bugs.webkit.org/show_bug.cgi?id=59843
+
+ Allows isolated worlds to be associated with a different SecurityOrigin
+ (exposed as a setIsolatedWorldSecurityOrigin function in
+ ScriptController).
+
+ The XMLHttpRequest constructor can then check that it's being
+ instantiated in an isolated world and use its security origin.
+ XMLHttpRequest, ThreadableLoader and DocumentThreadableLoader had to be
+ changed to use the copied SecurityOrigin instead of always grabbing the
+ Document's.
+
+ Test: http/tests/security/isolatedWorld/cross-origin-xhr.html
+
+ * bindings/v8/ScriptController.cpp:
+ (WebCore::ScriptController::setIsolatedWorldSecurityOrigin):
+ * bindings/v8/ScriptController.h:
+ * bindings/v8/V8IsolatedContext.cpp:
+ (WebCore::V8IsolatedContext::setSecurityOrigin):
+ * bindings/v8/V8IsolatedContext.h:
+ (WebCore::V8IsolatedContext::securityOrigin):
+ * bindings/v8/V8Proxy.cpp:
+ (WebCore::V8Proxy::evaluateInIsolatedWorld):
+ (WebCore::V8Proxy::setIsolatedWorldSecurityOrigin):
+ (WebCore::V8Proxy::resetIsolatedWorlds):
+ * bindings/v8/V8Proxy.h:
+ * bindings/v8/custom/V8XMLHttpRequestConstructor.cpp:
+ (WebCore::V8XMLHttpRequest::constructorCallback):
+ * loader/DocumentThreadableLoader.cpp:
+ (WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
+ (WebCore::DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight):
+ (WebCore::DocumentThreadableLoader::didReceiveResponse):
+ (WebCore::DocumentThreadableLoader::preflightSuccess):
+ (WebCore::DocumentThreadableLoader::isAllowedRedirect):
+ (WebCore::DocumentThreadableLoader::securityOrigin):
+ * loader/DocumentThreadableLoader.h:
+ * loader/ThreadableLoader.h:
+ * xml/XMLHttpRequest.cpp:
+ (WebCore::XMLHttpRequest::create):
+ (WebCore::XMLHttpRequest::XMLHttpRequest):
+ (WebCore::XMLHttpRequest::securityOrigin):
+ (WebCore::XMLHttpRequest::responseXML):
+ (WebCore::XMLHttpRequest::createRequest):
+ (WebCore::XMLHttpRequest::setRequestHeader):
+ (WebCore::XMLHttpRequest::getAllResponseHeaders):
+ (WebCore::XMLHttpRequest::getResponseHeader):
+ * xml/XMLHttpRequest.h:
+
2011-05-26 Michael Nordman <michaeln@google.com>
Reviewed by Darin Fisher.
m_proxy->evaluateInIsolatedWorld(worldID, sources, extensionGroup);
}
+void ScriptController::setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin> securityOrigin)
+{
+ m_proxy->setIsolatedWorldSecurityOrigin(worldID, securityOrigin);
+}
+
// Evaluate a script file in the environment of this proxy.
ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)
{
// FIXME: Get rid of extensionGroup here.
void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&, int extensionGroup);
+ // Associates an isolated world (see above for description) with a security
+ // origin. XMLHttpRequest instances used in that world will be considered
+ // to come from that origin, not the frame's.
+ void setIsolatedWorldSecurityOrigin(int worldId, PassRefPtr<SecurityOrigin>);
+
// Masquerade 'this' as the windowShell.
// This is a bit of a hack, but provides reasonable compatibility
// with what JSC does as well.
#include "Frame.h"
#include "FrameLoaderClient.h"
-#include "HashMap.h"
+#include "SecurityOrigin.h"
#include "V8DOMWindow.h"
#include "V8HiddenPropertyName.h"
m_context->disposeHandle();
}
+void V8IsolatedContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin)
+{
+ m_securityOrigin = securityOrigin;
+}
+
} // namespace WebCore
namespace WebCore {
+class SecurityOrigin;
class V8Proxy;
// V8IsolatedContext
public:
// Creates an isolated world. To destroy it, call destroy().
// This will delete the isolated world when the context it owns is GC'd.
- V8IsolatedContext(V8Proxy* proxy, int extensionGroup);
+ V8IsolatedContext(V8Proxy*, int extensionGroup);
~V8IsolatedContext();
// Call this to destroy the isolated world. It will be deleted sometime
IsolatedWorld* world() const { return m_world.get(); }
+ SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); }
+ void setSecurityOrigin(PassRefPtr<SecurityOrigin>);
+
private:
static v8::Handle<v8::Object> getGlobalObject(v8::Handle<v8::Context> context)
{
RefPtr<SharedPersistent<v8::Context> > m_context;
RefPtr<IsolatedWorld> m_world;
+
+ RefPtr<SecurityOrigin> m_securityOrigin;
};
} // namespace WebCore
#include "PageGroup.h"
#include "PlatformBridge.h"
#include "ScriptSourceCode.h"
+#include "SecurityOrigin.h"
#include "Settings.h"
#include "StorageNamespace.h"
#include "V8Binding.h"
return;
}
}
+
+ IsolatedWorldSecurityOriginMap::iterator securityOriginIter = m_isolatedWorldSecurityOrigins.find(worldID);
+ if (securityOriginIter != m_isolatedWorldSecurityOrigins.end())
+ isolatedContext->setSecurityOrigin(securityOriginIter->second);
} else {
isolatedContext = new V8IsolatedContext(this, extensionGroup);
if (isolatedContext->context().IsEmpty()) {
isolatedContext->destroy();
}
+void V8Proxy::setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin> prpSecurityOriginIn)
+{
+ ASSERT(worldID);
+ RefPtr<SecurityOrigin> securityOrigin = prpSecurityOriginIn;
+ m_isolatedWorldSecurityOrigins.set(worldID, securityOrigin);
+ IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(worldID);
+ if (iter != m_isolatedWorlds.end())
+ iter->second->setSecurityOrigin(securityOrigin);
+}
+
bool V8Proxy::setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContext)
{
// Setup context id for JS debugger.
iter->second->destroy();
}
m_isolatedWorlds.clear();
+ m_isolatedWorldSecurityOrigins.clear();
}
void V8Proxy::clearForClose()
class Node;
class ScriptExecutionContext;
class ScriptSourceCode;
+ class SecurityOrigin;
class V8EventListener;
class V8IsolatedContext;
class WorldContextHandle;
// Array, and so-on), and its own wrappers for all DOM nodes and DOM
// constructors.
void evaluateInIsolatedWorld(int worldId, const Vector<ScriptSourceCode>& sources, int extensionGroup);
+
+ void setIsolatedWorldSecurityOrigin(int worldId, PassRefPtr<SecurityOrigin>);
// Returns true if the proxy is currently executing a script in V8.
bool executingScript() const;
// IsolatedContext directly.
typedef HashMap<int, V8IsolatedContext*> IsolatedWorldMap;
IsolatedWorldMap m_isolatedWorlds;
+
+ typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap;
+ IsolatedWorldSecurityOriginMap m_isolatedWorldSecurityOrigins;
};
template <typename T>
#include "V8XMLHttpRequest.h"
#include "Frame.h"
+#include "OriginAccessEntry.h"
+#include "SecurityOrigin.h"
#include "V8Binding.h"
+#include "V8IsolatedContext.h"
#include "V8Proxy.h"
#include "V8Utilities.h"
#include "WorkerContext.h"
ScriptExecutionContext* context = getScriptExecutionContext();
if (!context)
return throwError("XMLHttpRequest constructor's associated context is not available", V8Proxy::ReferenceError);
- RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context);
+
+ RefPtr<SecurityOrigin> securityOrigin;
+ if (V8IsolatedContext* isolatedContext = V8IsolatedContext::getEntered())
+ securityOrigin = isolatedContext->securityOrigin();
+ RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin);
V8DOMWrapper::setDOMWrapper(args.Holder(), &info, xmlHttpRequest.get());
// Add object to the wrapper map.
, m_document(document)
, m_options(options)
, m_optionalOutgoingReferrer(optionalOutgoingReferrer)
- , m_sameOriginRequest(document->securityOrigin()->canRequest(request.url()))
+ , m_sameOriginRequest(securityOrigin()->canRequest(request.url()))
, m_async(blockingBehavior == LoadAsynchronously)
{
ASSERT(document);
ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
OwnPtr<ResourceRequest> crossOriginRequest = adoptPtr(new ResourceRequest(request));
- updateRequestForAccessControl(*crossOriginRequest, m_document->securityOrigin(), m_options.allowCredentials);
+ updateRequestForAccessControl(*crossOriginRequest, securityOrigin(), m_options.allowCredentials);
if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields()))
makeSimpleCrossOriginAccessRequest(*crossOriginRequest);
else {
m_actualRequest = crossOriginRequest.release();
- if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields()))
+ if (CrossOriginPreflightResultCache::shared().canSkipPreflight(securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields()))
preflightSuccess();
else
makeCrossOriginAccessRequestWithPreflight(*m_actualRequest);
void DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request)
{
- ResourceRequest preflightRequest = createAccessControlPreflightRequest(request, m_document->securityOrigin(), m_options.allowCredentials);
+ ResourceRequest preflightRequest = createAccessControlPreflightRequest(request, securityOrigin(), m_options.allowCredentials);
loadRequest(preflightRequest, DoSecurityCheck);
}
String accessControlErrorDescription;
if (m_actualRequest) {
- if (!passesAccessControlCheck(response, m_options.allowCredentials, m_document->securityOrigin(), accessControlErrorDescription)) {
+ if (!passesAccessControlCheck(response, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription)) {
preflightFailure(response.url(), accessControlErrorDescription);
return;
}
return;
}
- CrossOriginPreflightResultCache::shared().appendEntry(m_document->securityOrigin()->toString(), m_actualRequest->url(), preflightResult.release());
+ CrossOriginPreflightResultCache::shared().appendEntry(securityOrigin()->toString(), m_actualRequest->url(), preflightResult.release());
} else {
if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) {
- if (!passesAccessControlCheck(response, m_options.allowCredentials, m_document->securityOrigin(), accessControlErrorDescription)) {
+ if (!passesAccessControlCheck(response, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription)) {
m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, response.url().string(), accessControlErrorDescription));
return;
}
OwnPtr<ResourceRequest> actualRequest;
actualRequest.swap(m_actualRequest);
- actualRequest->setHTTPOrigin(m_document->securityOrigin()->toString());
+ actualRequest->setHTTPOrigin(securityOrigin()->toString());
// It should be ok to skip the security check since we already asked about the preflight request.
loadRequest(*actualRequest, SkipSecurityCheck);
// FIXME: We need to implement access control for each redirect. This will require some refactoring though, because the code
// that processes redirects doesn't know about access control and expects a synchronous answer from its client about whether
// a redirect should proceed.
- return m_sameOriginRequest && m_document->securityOrigin()->canRequest(url);
+ return m_sameOriginRequest && securityOrigin()->canRequest(url);
+}
+
+SecurityOrigin* DocumentThreadableLoader::securityOrigin() const
+{
+ return m_options.securityOrigin ? m_options.securityOrigin.get() : m_document->securityOrigin();
}
} // namespace WebCore
class Document;
class KURL;
class ResourceRequest;
+ class SecurityOrigin;
class ThreadableLoaderClient;
class DocumentThreadableLoader : public RefCounted<DocumentThreadableLoader>, public ThreadableLoader, private SubresourceLoaderClient {
void loadRequest(const ResourceRequest&, SecurityCheckPolicy);
bool isAllowedRedirect(const KURL&);
+ SecurityOrigin* securityOrigin() const;
+
RefPtr<SubresourceLoader> m_loader;
ThreadableLoaderClient* m_client;
Document* m_document;
#ifndef ThreadableLoader_h
#define ThreadableLoader_h
+#include "SecurityOrigin.h"
#include <wtf/Noncopyable.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
bool forcePreflight; // If AccessControl is used, whether to force a preflight.
CrossOriginRequestPolicy crossOriginRequestPolicy;
bool shouldBufferData;
+ RefPtr<SecurityOrigin> securityOrigin;
};
// Useful for doing loader operations from any thread (not threadsafe,
return dummy;
}
-XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context)
+PassRefPtr<XMLHttpRequest> XMLHttpRequest::create(ScriptExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
+{
+ return adoptRef(new XMLHttpRequest(context, securityOrigin));
+}
+
+XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
: ActiveDOMObject(context, this)
, m_async(true)
, m_includeCredentials(false)
, m_exceptionCode(0)
, m_progressEventThrottle(this)
, m_responseTypeCode(ResponseTypeDefault)
+ , m_securityOrigin(securityOrigin)
{
initializeXMLHttpRequestStaticData();
#ifndef NDEBUG
return static_cast<Document*>(scriptExecutionContext());
}
+SecurityOrigin* XMLHttpRequest::securityOrigin() const
+{
+ return m_securityOrigin ? m_securityOrigin.get() : scriptExecutionContext()->securityOrigin();
+}
+
#if ENABLE(DASHBOARD_SUPPORT)
bool XMLHttpRequest::usesDashboardBackwardCompatibilityMode() const
{
m_responseXML = Document::create(0, m_url);
// FIXME: Set Last-Modified.
m_responseXML->setContent(m_responseBuilder.toStringPreserveCapacity());
- m_responseXML->setSecurityOrigin(document()->securityOrigin());
+ m_responseXML->setSecurityOrigin(securityOrigin());
if (!m_responseXML->wellFormed())
m_responseXML = 0;
}
}
}
- m_sameOriginRequest = scriptExecutionContext()->securityOrigin()->canRequest(m_url);
+ m_sameOriginRequest = securityOrigin()->canRequest(m_url);
// We also remember whether upload events should be allowed for this request in case the upload listeners are
// added after the request is started.
options.forcePreflight = uploadEvents;
options.allowCredentials = m_sameOriginRequest || m_includeCredentials;
options.crossOriginRequestPolicy = UseAccessControl;
+ options.securityOrigin = securityOrigin();
m_exceptionCode = 0;
m_error = false;
}
// A privileged script (e.g. a Dashboard widget) can set any headers.
- if (!scriptExecutionContext()->securityOrigin()->canLoadLocalResources() && !isSafeRequestHeader(name)) {
+ if (!securityOrigin()->canLoadLocalResources() && !isSafeRequestHeader(name)) {
reportUnsafeUsage(scriptExecutionContext(), "Refused to set unsafe header \"" + name + "\"");
return;
}
// 2) There's no known harm in hiding Set-Cookie header fields entirely; we don't
// know any widely used technique that requires access to them.
// 3) Firefox has implemented this policy.
- if (isSetCookieHeader(it->first) && !scriptExecutionContext()->securityOrigin()->canLoadLocalResources())
+ if (isSetCookieHeader(it->first) && !securityOrigin()->canLoadLocalResources())
continue;
if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->first))
}
// See comment in getAllResponseHeaders above.
- if (isSetCookieHeader(name) && !scriptExecutionContext()->securityOrigin()->canLoadLocalResources()) {
+ if (isSetCookieHeader(name) && !securityOrigin()->canLoadLocalResources()) {
reportUnsafeUsage(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
return String();
}
class Document;
class DOMFormData;
class ResourceRequest;
+class SecurityOrigin;
class SharedBuffer;
class TextResourceDecoder;
class ThreadableLoader;
class XMLHttpRequest : public RefCounted<XMLHttpRequest>, public EventTarget, private ThreadableLoaderClient, public ActiveDOMObject {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<XMLHttpRequest> create(ScriptExecutionContext* context) { return adoptRef(new XMLHttpRequest(context)); }
+ static PassRefPtr<XMLHttpRequest> create(ScriptExecutionContext*, PassRefPtr<SecurityOrigin> = 0);
~XMLHttpRequest();
// These exact numeric values are important because JS expects them.
using RefCounted<XMLHttpRequest>::deref;
private:
- XMLHttpRequest(ScriptExecutionContext*);
+ XMLHttpRequest(ScriptExecutionContext*, PassRefPtr<SecurityOrigin>);
virtual void refEventTarget() { ref(); }
virtual void derefEventTarget() { deref(); }
virtual EventTargetData* ensureEventTargetData();
Document* document() const;
+ SecurityOrigin* securityOrigin() const;
#if ENABLE(DASHBOARD_SUPPORT)
bool usesDashboardBackwardCompatibilityMode() const;
// An enum corresponding to the allowed string values for the responseType attribute.
ResponseTypeCode m_responseTypeCode;
+
+ RefPtr<SecurityOrigin> m_securityOrigin;
};
} // namespace WebCore
+2011-05-26 Mihai Parparita <mihaip@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Support cross-origin XMLHttpRequest in isolated worlds
+ https://bugs.webkit.org/show_bug.cgi?id=59843
+
+ Expose setIsolatedWorldSecurityOrigin in the WebFrame API.
+
+ * public/WebFrame.h:
+ * src/WebFrameImpl.cpp:
+ (WebKit::WebFrameImpl::setIsolatedWorldSecurityOrigin):
+ * src/WebFrameImpl.h:
+
2011-05-26 Michael Nordman <michaeln@google.com>
Reviewed by Darin Fisher.
int worldId, const WebScriptSource* sources, unsigned numSources,
int extensionGroup) = 0;
+ // Associates an isolated world (see above for description) with a security
+ // origin. XMLHttpRequest instances used in that world will be considered
+ // to come from that origin, not the frame's.
+ virtual void setIsolatedWorldSecurityOrigin(
+ int worldId, const WebSecurityOrigin&) = 0;
+
// Logs to the console associated with this frame.
virtual void addMessageToConsole(const WebConsoleMessage&) = 0;
m_frame->script()->evaluateInIsolatedWorld(worldId, sources, extensionGroup);
}
+void WebFrameImpl::setIsolatedWorldSecurityOrigin(int worldId, const WebSecurityOrigin& securityOrigin)
+{
+ m_frame->script()->setIsolatedWorldSecurityOrigin(worldId, securityOrigin.get());
+}
+
void WebFrameImpl::addMessageToConsole(const WebConsoleMessage& message)
{
ASSERT(frame());
virtual void executeScriptInIsolatedWorld(
int worldId, const WebScriptSource* sources, unsigned numSources,
int extensionGroup);
+ virtual void setIsolatedWorldSecurityOrigin(int worldId, const WebSecurityOrigin&);
virtual void addMessageToConsole(const WebConsoleMessage&);
virtual void collectGarbage();
#if WEBKIT_USING_V8
+2011-05-26 Mihai Parparita <mihaip@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Support cross-origin XMLHttpRequest in isolated worlds
+ https://bugs.webkit.org/show_bug.cgi?id=59843
+
+ Expose setIsolatedWorldSecurityOrigin in LayoutTestController.
+
+ * DumpRenderTree/chromium/LayoutTestController.cpp:
+ (LayoutTestController::LayoutTestController):
+ (LayoutTestController::setIsolatedWorldSecurityOrigin):
+ * DumpRenderTree/chromium/LayoutTestController.h:
+
2011-05-25 Brian Weinstein <bweinstein@apple.com>
Reviewed by Adam Roben.
bindMethod("ensureShadowRoot", &LayoutTestController::ensureShadowRoot);
bindMethod("evaluateInWebInspector", &LayoutTestController::evaluateInWebInspector);
bindMethod("evaluateScriptInIsolatedWorld", &LayoutTestController::evaluateScriptInIsolatedWorld);
+ bindMethod("setIsolatedWorldSecurityOrigin", &LayoutTestController::setIsolatedWorldSecurityOrigin);
bindMethod("execCommand", &LayoutTestController::execCommand);
bindMethod("grantDesktopNotificationPermission", &LayoutTestController::grantDesktopNotificationPermission);
bindMethod("hasSpellingMarker", &LayoutTestController::hasSpellingMarker);
result->setNull();
}
+void LayoutTestController::setIsolatedWorldSecurityOrigin(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+
+ if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isString())
+ return;
+
+ m_shell->webView()->focusedFrame()->setIsolatedWorldSecurityOrigin(
+ arguments[0].toInt32(),
+ WebSecurityOrigin::createFromString(cppVariantToWebString(arguments[1])));
+}
+
void LayoutTestController::setAllowUniversalAccessFromFileURLs(const CppArgumentList& arguments, CppVariant* result)
{
if (arguments.size() > 0 && arguments[0].isBool()) {
void setJavaScriptCanAccessClipboard(const CppArgumentList&, CppVariant*);
void setXSSAuditorEnabled(const CppArgumentList&, CppVariant*);
- void evaluateScriptInIsolatedWorld(const CppArgumentList&, CppVariant*);
void overridePreference(const CppArgumentList&, CppVariant*);
void setAllowUniversalAccessFromFileURLs(const CppArgumentList&, CppVariant*);
void setAllowDisplayOfInsecureContent(const CppArgumentList&, CppVariant*);
void setAllowFileAccessFromFileURLs(const CppArgumentList&, CppVariant*);
void setAllowRunningOfInsecureContent(const CppArgumentList&, CppVariant*);
+ void evaluateScriptInIsolatedWorld(const CppArgumentList&, CppVariant*);
+ void setIsolatedWorldSecurityOrigin(const CppArgumentList&, CppVariant*);
+
void shadowRoot(const CppArgumentList&, CppVariant*);
void ensureShadowRoot(const CppArgumentList&, CppVariant*);
void removeShadowRoot(const CppArgumentList&, CppVariant*);