Reviewed by Sam.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jul 2007 06:29:48 +0000 (06:29 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jul 2007 06:29:48 +0000 (06:29 +0000)
        - fixed <rdar://problem/5220706> REGRESSION (TOT): repro crash in -[WebView(WebViewInternal) _addObject:forIdentifier:] [14425]
        http://bugs.webkit.org/show_bug.cgi?id=14425

        * bindings/js/kjs_window.cpp:
        (KJS::createWindow): No longer take an immediate argument - always do immediate loads
        on a newly created Window. Also, do a load of "" to make sure that the right info makes
        it to the app.
        (KJS::showModalDialog): Updated for above.
        (KJS::WindowFunc::callAsFunction): Updated for above.
        * dom/Document.cpp:
        (WebCore::Document::shouldBeAllowedToLoadLocalResources): If our URL is about:blank,
        we're allowed if our opener is (since the opener must have written the contents).
        * loader/FrameLoader.cpp:
        (WebCore::FrameLoader::changeLocation): Add a variant which takes a KURL, which it
        expects to be pre-completed. This is to avoid completing "" to the opener URL.
        (WebCore::FrameLoader::urlSelected): Allow loading empty URLs.
        * loader/FrameLoader.h:

        Test case is manual only, since it takes particular app behavior to reproduce:

        * manual-tests/new-window-subresource-crash.html: Added.

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

WebCore/ChangeLog
WebCore/bindings/js/kjs_window.cpp
WebCore/dom/Document.cpp
WebCore/loader/FrameLoader.cpp
WebCore/loader/FrameLoader.h
WebCore/manual-tests/new-window-subresource-crash.html [new file with mode: 0644]

index 5c84f64..04cb785 100644 (file)
@@ -1,3 +1,29 @@
+2007-07-08  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Sam.
+
+        - fixed <rdar://problem/5220706> REGRESSION (TOT): repro crash in -[WebView(WebViewInternal) _addObject:forIdentifier:] [14425]
+        http://bugs.webkit.org/show_bug.cgi?id=14425
+
+        * bindings/js/kjs_window.cpp:
+        (KJS::createWindow): No longer take an immediate argument - always do immediate loads
+        on a newly created Window. Also, do a load of "" to make sure that the right info makes
+        it to the app.
+        (KJS::showModalDialog): Updated for above.
+        (KJS::WindowFunc::callAsFunction): Updated for above.
+        * dom/Document.cpp:
+        (WebCore::Document::shouldBeAllowedToLoadLocalResources): If our URL is about:blank,
+        we're allowed if our opener is (since the opener must have written the contents).
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::changeLocation): Add a variant which takes a KURL, which it
+        expects to be pre-completed. This is to avoid completing "" to the opener URL.
+        (WebCore::FrameLoader::urlSelected): Allow loading empty URLs.
+        * loader/FrameLoader.h:
+        
+        Test case is manual only, since it takes particular app behavior to reproduce:
+        
+        * manual-tests/new-window-subresource-crash.html: Added.
+
 2007-07-08  Mitz Pettel  <mitz@webkit.org>
 
         Reviewed by Maciej.
index 0a152fc..cfd9756 100644 (file)
@@ -391,7 +391,7 @@ static float floatFeature(const HashMap<String, String> &features, const char *k
 }
 
 static Frame* createWindow(ExecState* exec, Frame* openerFrame, const String& url,
-    const String& frameName, const WindowFeatures& windowFeatures, JSValue* dialogArgs, bool immediate)
+    const String& frameName, const WindowFeatures& windowFeatures, JSValue* dialogArgs)
 {
     Frame* activeFrame = Window::retrieveActive(exec)->frame();
     
@@ -420,19 +420,17 @@ static Frame* createWindow(ExecState* exec, Frame* openerFrame, const String& ur
     if (dialogArgs)
         newWindow->putDirect("dialogArguments", dialogArgs);
 
-    if (created)
-        if (Document* oldDoc = openerFrame->document()) {
-            newFrame->document()->setDomain(oldDoc->domain(), true);
-            newFrame->document()->setBaseURL(oldDoc->baseURL());
-        }
-        
-    if (!url.isEmpty() && (!url.startsWith("javascript:", false) || newWindow->isSafeScript(exec))) {
-        String completedURL = activeFrame->document()->completeURL(url);
+    if (!url.startsWith("javascript:", false) || newWindow->isSafeScript(exec)) {
+        String completedURL = url.isEmpty() ? url : activeFrame->document()->completeURL(url);
         bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
         
-        if (immediate)
-            newFrame->loader()->changeLocation(completedURL, activeFrame->loader()->outgoingReferrer(), false, userGesture);
-        else
+        if (created) {
+            newFrame->loader()->changeLocation(KURL(completedURL.deprecatedString()), activeFrame->loader()->outgoingReferrer(), false, userGesture);
+            if (Document* oldDoc = openerFrame->document()) {
+                newFrame->document()->setDomain(oldDoc->domain(), true);
+                newFrame->document()->setBaseURL(oldDoc->baseURL());
+            }
+        } else if (!url.isEmpty())
             newFrame->loader()->scheduleLocationChange(completedURL, activeFrame->loader()->outgoingReferrer(), false, userGesture);
     }
     
@@ -504,7 +502,7 @@ static JSValue* showModalDialog(ExecState* exec, Window* openerWindow, const Lis
     wargs.locationBarVisible = false;
     wargs.fullscreen = false;
     
-    Frame* dialogFrame = createWindow(exec, openerWindow->frame(), valueToStringWithUndefinedOrNullCheck(exec, args[0]), "", wargs, args[1], true);
+    Frame* dialogFrame = createWindow(exec, openerWindow->frame(), valueToStringWithUndefinedOrNullCheck(exec, args[0]), "", wargs, args[1]);
     if (!dialogFrame)
         return jsUndefined();
 
@@ -1453,7 +1451,7 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
       parseWindowFeatures(features, windowFeatures);
       constrainToVisible(screenRect(page->mainFrame()->view()), windowFeatures);
 
-      frame = createWindow(exec, frame, urlString, frameName, windowFeatures, 0, false);
+      frame = createWindow(exec, frame, urlString, frameName, windowFeatures, 0);
 
       if (!frame)
           return jsUndefined();
index d67a1a2..48c85dc 100644 (file)
@@ -1550,6 +1550,9 @@ bool Document::shouldBeAllowedToLoadLocalResources() const
     DocumentLoader* documentLoader = frame->loader()->documentLoader();
     if (!documentLoader)
         return false;
+
+    if (m_url == "about:blank" && frame->loader()->opener() && frame->loader()->opener()->document()->isAllowedToLoadLocalResources())
+        return true;
     
     return documentLoader->substituteData().isValid();
 }
index dcae6bd..24cb09c 100644 (file)
@@ -346,8 +346,13 @@ bool FrameLoader::canHandleRequest(const ResourceRequest& request)
 
 void FrameLoader::changeLocation(const String& URL, const String& referrer, bool lockHistory, bool userGesture)
 {
-    if (URL.find("javascript:", 0, false) == 0) {
-        String script = KURL::decode_string(URL.substring(strlen("javascript:")).deprecatedString());
+    changeLocation(completeURL(URL), referrer, lockHistory, userGesture);
+}
+
+void FrameLoader::changeLocation(const KURL& URL, const String& referrer, bool lockHistory, bool userGesture)
+{
+    if (URL.url().find("javascript:", 0, false) == 0) {
+        String script = KURL::decode_string(URL.url().mid(strlen("javascript:")));
         JSValue* result = executeScript(0, script, userGesture);
         String scriptResult;
         if (getString(result, scriptResult)) {
@@ -360,7 +365,7 @@ void FrameLoader::changeLocation(const String& URL, const String& referrer, bool
 
     ResourceRequestCachePolicy policy = (m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh)
         ? ReloadIgnoringCacheData : UseProtocolCachePolicy;
-    ResourceRequest request(completeURL(URL), referrer, policy);
+    ResourceRequest request(URL, referrer, policy);
     
     urlSelected(request, "_self", 0, lockHistory, userGesture);
 }
@@ -377,7 +382,7 @@ void FrameLoader::urlSelected(const ResourceRequest& request, const String& _tar
         return;
     }
 
-    if (!url.isValid())
+    if (!url.isValid() && !url.isEmpty())
         return;
 
     FrameLoadRequest frameRequest(request, target);
index f16c875..eec03fe 100644 (file)
@@ -273,6 +273,7 @@ namespace WebCore {
         void setDefersLoading(bool);
 
         void changeLocation(const String& URL, const String& referrer, bool lockHistory = true, bool userGesture = false);
+        void changeLocation(const KURL& URL, const String& referrer, bool lockHistory = true, bool userGesture = false);
         void urlSelected(const ResourceRequest&, const String& target, Event*, bool lockHistory, bool userGesture);
         void urlSelected(const FrameLoadRequest&, Event*, bool userGesture);
       
diff --git a/WebCore/manual-tests/new-window-subresource-crash.html b/WebCore/manual-tests/new-window-subresource-crash.html
new file mode 100644 (file)
index 0000000..b287d90
--- /dev/null
@@ -0,0 +1,20 @@
+<body onload="test()">
+<script>
+    function test()
+    {
+        var win = window.open("");
+        var doc = win.document;
+        var text = "<html><body><sc" + "ript src='data:text/javascript,'></scr" + "ipt></body></html>";
+        doc.write(text);
+    }
+</script>
+
+<p>This test verifies that document.writing into a newly-opened empty
+window does not cause crashes or assertion failures, even if it
+triggers subresource loads. If you have popup blocking enabled you can
+click the button below to test. The test only works in Safari, because
+it depends on behavior with resource identifiers, which are provided
+by the app.</p>
+
+<button onclick="test()">Crash</button>
+</body>