2011-05-26 Mihai Parparita <mihaip@chromium.org>
authormihaip@chromium.org <mihaip@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 May 2011 19:53:00 +0000 (19:53 +0000)
committermihaip@chromium.org <mihaip@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 May 2011 19:53:00 +0000 (19:53 +0000)
        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

28 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/isolatedWorld/cross-origin-xhr.html [new file with mode: 0644]
LayoutTests/http/tests/security/isolatedWorld/resources/cross-origin-xhr.txt [new file with mode: 0644]
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/mac/Skipped
LayoutTests/platform/qt/Skipped
LayoutTests/platform/win/Skipped
Source/WebCore/ChangeLog
Source/WebCore/bindings/v8/ScriptController.cpp
Source/WebCore/bindings/v8/ScriptController.h
Source/WebCore/bindings/v8/V8IsolatedContext.cpp
Source/WebCore/bindings/v8/V8IsolatedContext.h
Source/WebCore/bindings/v8/V8Proxy.cpp
Source/WebCore/bindings/v8/V8Proxy.h
Source/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp
Source/WebCore/loader/DocumentThreadableLoader.cpp
Source/WebCore/loader/DocumentThreadableLoader.h
Source/WebCore/loader/ThreadableLoader.h
Source/WebCore/xml/XMLHttpRequest.cpp
Source/WebCore/xml/XMLHttpRequest.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/public/WebFrame.h
Source/WebKit/chromium/src/WebFrameImpl.cpp
Source/WebKit/chromium/src/WebFrameImpl.h
Tools/ChangeLog
Tools/DumpRenderTree/chromium/LayoutTestController.cpp
Tools/DumpRenderTree/chromium/LayoutTestController.h

index d1c1cc4..68eada9 100644 (file)
@@ -1,3 +1,23 @@
+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.
diff --git a/LayoutTests/http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt b/LayoutTests/http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt
new file mode 100644 (file)
index 0000000..27df05b
--- /dev/null
@@ -0,0 +1,22 @@
+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
+
diff --git a/LayoutTests/http/tests/security/isolatedWorld/cross-origin-xhr.html b/LayoutTests/http/tests/security/isolatedWorld/cross-origin-xhr.html
new file mode 100644 (file)
index 0000000..1c282f6
--- /dev/null
@@ -0,0 +1,103 @@
+<!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>
diff --git a/LayoutTests/http/tests/security/isolatedWorld/resources/cross-origin-xhr.txt b/LayoutTests/http/tests/security/isolatedWorld/resources/cross-origin-xhr.txt
new file mode 100644 (file)
index 0000000..b1e9c92
--- /dev/null
@@ -0,0 +1 @@
+Test file for cross-origin XMLHttpRequest tests.
index bd5631b..75f2fe4 100644 (file)
@@ -1456,3 +1456,6 @@ fast/events/scroll-in-scaled-page-with-overflow-hidden.html
 
 # 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
index 4f85e53..c306325 100644 (file)
@@ -362,3 +362,6 @@ inspector/console/console-long-eval-crash.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
index 87a6e36..6fd196f 100644 (file)
@@ -2514,3 +2514,6 @@ fast/events/remove-target-in-mouseup.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
index 5afde47..a423c43 100644 (file)
@@ -1305,3 +1305,6 @@ fast/events/page-visibility-transition-test.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
index d1e544f..acda793 100644 (file)
@@ -1,3 +1,56 @@
+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.
index b5c89d8..b9677f1 100644 (file)
@@ -216,6 +216,11 @@ void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<Sc
     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)
 {
index 6b9765c..5b2f483 100644 (file)
@@ -99,6 +99,11 @@ public:
     // 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.
index 7b21a36..62015d7 100644 (file)
@@ -34,7 +34,7 @@
 
 #include "Frame.h"
 #include "FrameLoaderClient.h"
-#include "HashMap.h"
+#include "SecurityOrigin.h"
 #include "V8DOMWindow.h"
 #include "V8HiddenPropertyName.h"
 
@@ -87,4 +87,9 @@ V8IsolatedContext::~V8IsolatedContext()
     m_context->disposeHandle();
 }
 
+void V8IsolatedContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin)
+{
+    m_securityOrigin = securityOrigin;
+}
+
 } // namespace WebCore
index 5cd9c65..6221dc3 100644 (file)
@@ -40,6 +40,7 @@
 
 namespace WebCore {
 
+class SecurityOrigin;
 class V8Proxy;
 
 // V8IsolatedContext
@@ -58,7 +59,7 @@ class 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
@@ -93,6 +94,9 @@ public:
 
     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)
     {
@@ -108,6 +112,8 @@ private:
     RefPtr<SharedPersistent<v8::Context> > m_context;
 
     RefPtr<IsolatedWorld> m_world;
+
+    RefPtr<SecurityOrigin> m_securityOrigin;
 };
 
 } // namespace WebCore
index fa69196..39e0254 100644 (file)
@@ -47,6 +47,7 @@
 #include "PageGroup.h"
 #include "PlatformBridge.h"
 #include "ScriptSourceCode.h"
+#include "SecurityOrigin.h"
 #include "Settings.h"
 #include "StorageNamespace.h"
 #include "V8Binding.h"
@@ -272,6 +273,10 @@ void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode
                 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()) {
@@ -289,6 +294,16 @@ void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode
       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.
@@ -621,6 +636,7 @@ void V8Proxy::resetIsolatedWorlds()
         iter->second->destroy();
     }
     m_isolatedWorlds.clear();
+    m_isolatedWorldSecurityOrigins.clear();
 }
 
 void V8Proxy::clearForClose()
index c344a2c..354800d 100644 (file)
@@ -59,6 +59,7 @@ namespace WebCore {
     class Node;
     class ScriptExecutionContext;
     class ScriptSourceCode;
+    class SecurityOrigin;
     class V8EventListener;
     class V8IsolatedContext;
     class WorldContextHandle;
@@ -159,6 +160,8 @@ namespace WebCore {
         // 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;
@@ -339,6 +342,9 @@ namespace WebCore {
         //        IsolatedContext directly.
         typedef HashMap<int, V8IsolatedContext*> IsolatedWorldMap;
         IsolatedWorldMap m_isolatedWorlds;
+        
+        typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap;
+        IsolatedWorldSecurityOriginMap m_isolatedWorldSecurityOrigins;
     };
 
     template <typename T>
index 6b5b64f..ba3d103 100644 (file)
 #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"
@@ -52,7 +55,11 @@ v8::Handle<v8::Value> V8XMLHttpRequest::constructorCallback(const v8::Arguments&
     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.
index 2f48fba..804c3e7 100644 (file)
@@ -68,7 +68,7 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl
     , 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);
@@ -89,14 +89,14 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl
     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);
@@ -119,7 +119,7 @@ void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const Resource
 
 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);
 }
 
@@ -176,7 +176,7 @@ void DocumentThreadableLoader::didReceiveResponse(SubresourceLoader* loader, con
 
     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;
         }
@@ -189,10 +189,10 @@ void DocumentThreadableLoader::didReceiveResponse(SubresourceLoader* loader, con
             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;
             }
@@ -293,7 +293,7 @@ void DocumentThreadableLoader::preflightSuccess()
     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);
@@ -368,7 +368,12 @@ bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url)
     // 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
index 50f60ca..5949667 100644 (file)
@@ -45,6 +45,7 @@ namespace WebCore {
     class Document;
     class KURL;
     class ResourceRequest;
+    class SecurityOrigin;
     class ThreadableLoaderClient;
 
     class DocumentThreadableLoader : public RefCounted<DocumentThreadableLoader>, public ThreadableLoader, private SubresourceLoaderClient  {
@@ -94,6 +95,8 @@ namespace WebCore {
         void loadRequest(const ResourceRequest&, SecurityCheckPolicy);
         bool isAllowedRedirect(const KURL&);
 
+        SecurityOrigin* securityOrigin() const;
+
         RefPtr<SubresourceLoader> m_loader;
         ThreadableLoaderClient* m_client;
         Document* m_document;
index b01f3ee..c02b4a5 100644 (file)
 #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 {
@@ -62,6 +64,7 @@ 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, 
index 73bb6ee..d73d11c 100644 (file)
@@ -172,7 +172,12 @@ static const XMLHttpRequestStaticData* initializeXMLHttpRequestStaticData()
     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)
@@ -187,6 +192,7 @@ XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context)
     , m_exceptionCode(0)
     , m_progressEventThrottle(this)
     , m_responseTypeCode(ResponseTypeDefault)
+    , m_securityOrigin(securityOrigin)
 {
     initializeXMLHttpRequestStaticData();
 #ifndef NDEBUG
@@ -207,6 +213,11 @@ Document* XMLHttpRequest::document() const
     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
 {
@@ -249,7 +260,7 @@ Document* XMLHttpRequest::responseXML(ExceptionCode& ec)
             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;
         }
@@ -617,7 +628,7 @@ void XMLHttpRequest::createRequest(ExceptionCode& ec)
         }
     }
 
-    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.
@@ -641,6 +652,7 @@ void XMLHttpRequest::createRequest(ExceptionCode& ec)
     options.forcePreflight = uploadEvents;
     options.allowCredentials = m_sameOriginRequest || m_includeCredentials;
     options.crossOriginRequestPolicy = UseAccessControl;
+    options.securityOrigin = securityOrigin();
 
     m_exceptionCode = 0;
     m_error = false;
@@ -823,7 +835,7 @@ void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& va
     }
 
     // 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;
     }
@@ -866,7 +878,7 @@ String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
         //     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))
@@ -891,7 +903,7 @@ String XMLHttpRequest::getResponseHeader(const AtomicString& name, ExceptionCode
     }
 
     // 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();
     }
index da777e7..b07ca2b 100644 (file)
@@ -39,6 +39,7 @@ class Blob;
 class Document;
 class DOMFormData;
 class ResourceRequest;
+class SecurityOrigin;
 class SharedBuffer;
 class TextResourceDecoder;
 class ThreadableLoader;
@@ -46,7 +47,7 @@ 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.
@@ -134,7 +135,7 @@ public:
     using RefCounted<XMLHttpRequest>::deref;
 
 private:
-    XMLHttpRequest(ScriptExecutionContext*);
+    XMLHttpRequest(ScriptExecutionContext*, PassRefPtr<SecurityOrigin>);
 
     virtual void refEventTarget() { ref(); }
     virtual void derefEventTarget() { deref(); }
@@ -142,6 +143,7 @@ private:
     virtual EventTargetData* ensureEventTargetData();
 
     Document* document() const;
+    SecurityOrigin* securityOrigin() const;
 
 #if ENABLE(DASHBOARD_SUPPORT)
     bool usesDashboardBackwardCompatibilityMode() const;
@@ -226,6 +228,8 @@ private:
 
     // An enum corresponding to the allowed string values for the responseType attribute.
     ResponseTypeCode m_responseTypeCode;
+
+    RefPtr<SecurityOrigin> m_securityOrigin;
 };
 
 } // namespace WebCore
index 9e845da..78737fd 100644 (file)
@@ -1,3 +1,17 @@
+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.
index 4e45d06..b77add3 100644 (file)
@@ -253,6 +253,12 @@ public:
         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;
 
index 418d500..7727ea5 100644 (file)
@@ -789,6 +789,11 @@ void WebFrameImpl::executeScriptInIsolatedWorld(
     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());
index 422cda8..b32784f 100644 (file)
@@ -104,6 +104,7 @@ public:
     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
index 8c3fc70..939c3a1 100644 (file)
@@ -1,3 +1,17 @@
+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.
index 33a5580..d4abbc7 100644 (file)
@@ -108,6 +108,7 @@ LayoutTestController::LayoutTestController(TestShell* shell)
     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);
@@ -1287,6 +1288,18 @@ void LayoutTestController::evaluateScriptInIsolatedWorld(const CppArgumentList&
     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()) {
index c4e95a7..252d4f1 100644 (file)
@@ -266,13 +266,15 @@ public:
 
     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*);