Bug 403331: update JAR channel URIs after a redirect. r=bz, r=jwalden (mochitest changes), sr=dveditz
authordcamp@mozilla.com
Mon, 26 Nov 2007 20:35:00 -0800
changeset 8361 3df985df43b09dc5b05fc21510daf0b8c3f3af1c
parent 8360 468435a1796e1e233b205f3459c4ca4fcced72db
child 8362 41ea0ce69d86b6abb987f87359cf1bc55f8cde88
push idunknown
push userunknown
push dateunknown
reviewersbz, jwalden, dveditz
bugs403331
milestone1.9b2pre
Bug 403331: update JAR channel URIs after a redirect. r=bz, r=jwalden (mochitest changes), sr=dveditz
modules/libjar/nsIJARURI.idl
modules/libjar/nsJARChannel.cpp
modules/libjar/nsJARURI.cpp
modules/libjar/test/Makefile.in
modules/libjar/test/mochitest/Makefile.in
modules/libjar/test/mochitest/bug403331.zip
modules/libjar/test/mochitest/bug403331.zip^headers^
modules/libjar/test/mochitest/test_bug403331.html
testing/mochitest/server.js
--- a/modules/libjar/nsIJARURI.idl
+++ b/modules/libjar/nsIJARURI.idl
@@ -42,23 +42,29 @@
  * JAR URLs have the following syntax
  *
  * jar:<jar-file-uri>!/<jar-entry>
  *
  * EXAMPLE: jar:http://www.big.com/blue.jar!/ocean.html
  *
  * The nsIURL methods operate on the <jar-entry> part of the spec.
  */
-[scriptable, uuid(d2746619-1724-4f42-8ca8-dacaf1b269d6)]
+[scriptable, uuid(b0922a89-f87b-4cb5-8612-305a285fcca7)]
 interface nsIJARURI : nsIURL {
 
     /**
      * Returns the root URI (the one for the actual JAR file) for this JAR
      * (e.g., http://www.big.com/blue.jar).
      */
     readonly attribute nsIURI JARFile;
 
     /**
      * Returns the entry specified for this JAR URI (e.g., "ocean.html").  This
      * value may contain %-escaped byte sequences.
      */
     attribute AUTF8String JAREntry;
+
+    /**
+     * Create a clone of the JAR URI with a new root URI (the URI for the
+     * actual JAR file).
+     */
+    nsIJARURI cloneWithJARFile(in nsIURI jarFile);
 };
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -696,25 +696,50 @@ nsJARChannel::AsyncOpen(nsIStreamListene
 
 NS_IMETHODIMP
 nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
                                  nsIRequest    *request,
                                  nsISupports   *context,
                                  nsresult       status,
                                  nsIFile       *file)
 {
+    nsresult rv;
+
     // Grab the security info from our base channel
     nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
-    if (channel)
+    if (channel) {
         channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
-    
+
+        PRUint32 loadFlags;
+        channel->GetLoadFlags(&loadFlags);
+        if (loadFlags & LOAD_REPLACE) {
+            mLoadFlags |= LOAD_REPLACE;
+
+            if (!mOriginalURI) {
+                SetOriginalURI(mJarURI);
+            }
+
+            nsCOMPtr<nsIURI> innerURI;
+            rv = channel->GetURI(getter_AddRefs(innerURI));
+            if (NS_SUCCEEDED(rv)) {
+                nsCOMPtr<nsIJARURI> newURI;
+                rv = mJarURI->CloneWithJARFile(innerURI,
+                                               getter_AddRefs(newURI));
+                if (NS_SUCCEEDED(rv)) {
+                    mJarURI = newURI;
+                }
+            }
+            status = rv;
+        }
+    }
+
     if (NS_SUCCEEDED(status)) {
         mJarFile = file;
     
-        nsresult rv = CreateJarInput(nsnull);
+        rv = CreateJarInput(nsnull);
         if (NS_SUCCEEDED(rv)) {
             // create input stream pump
             rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput);
             if (NS_SUCCEEDED(rv))
                 rv = mPump->AsyncRead(this, nsnull);
         }
         status = rv;
     }
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -494,41 +494,21 @@ nsJARURI::SchemeIs(const char *i_Scheme,
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsJARURI::Clone(nsIURI **result)
 {
     nsresult rv;
 
-    nsCOMPtr<nsIURI> newJARFile;
-    rv = mJARFile->Clone(getter_AddRefs(newJARFile));
-    if (NS_FAILED(rv)) return rv;
-
-    NS_TryToSetImmutable(newJARFile);
-
-    nsCOMPtr<nsIURI> newJAREntryURI;
-    rv = mJAREntry->Clone(getter_AddRefs(newJAREntryURI));
+    nsCOMPtr<nsIJARURI> uri;
+    rv = CloneWithJARFile(mJARFile, getter_AddRefs(uri));
     if (NS_FAILED(rv)) return rv;
 
-    nsCOMPtr<nsIURL> newJAREntry(do_QueryInterface(newJAREntryURI));
-    NS_ASSERTION(newJAREntry, "This had better QI to nsIURL!");
-    
-    nsJARURI* uri = new nsJARURI();
-    if (uri) {
-        NS_ADDREF(uri);
-        uri->mJARFile = newJARFile;
-        uri->mJAREntry = newJAREntry;
-        *result = uri;
-        rv = NS_OK;
-    } else {
-        rv = NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    return rv;
+    return CallQueryInterface(uri, result);
 }
 
 NS_IMETHODIMP
 nsJARURI::Resolve(const nsACString &relativePath, nsACString &result)
 {
     nsresult rv;
 
     nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv));
@@ -780,16 +760,52 @@ nsJARURI::GetJAREntry(nsACString &entryP
 
 NS_IMETHODIMP
 nsJARURI::SetJAREntry(const nsACString &entryPath)
 {
     return CreateEntryURL(entryPath, mCharsetHint.get(),
                           getter_AddRefs(mJAREntry));
 }
 
+NS_IMETHODIMP
+nsJARURI::CloneWithJARFile(nsIURI *jarFile, nsIJARURI **result)
+{
+    if (!jarFile) {
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    nsresult rv;
+
+    nsCOMPtr<nsIURI> newJARFile;
+    rv = jarFile->Clone(getter_AddRefs(newJARFile));
+    if (NS_FAILED(rv)) return rv;
+
+    NS_TryToSetImmutable(newJARFile);
+
+    nsCOMPtr<nsIURI> newJAREntryURI;
+    rv = mJAREntry->Clone(getter_AddRefs(newJAREntryURI));
+    if (NS_FAILED(rv)) return rv;
+
+    nsCOMPtr<nsIURL> newJAREntry(do_QueryInterface(newJAREntryURI));
+    NS_ASSERTION(newJAREntry, "This had better QI to nsIURL!");
+    
+    nsJARURI* uri = new nsJARURI();
+    if (uri) {
+        NS_ADDREF(uri);
+        uri->mJARFile = newJARFile;
+        uri->mJAREntry = newJAREntry;
+        *result = uri;
+        rv = NS_OK;
+    } else {
+        rv = NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    return rv;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMETHODIMP
 nsJARURI::GetInnerURI(nsIURI **uri)
 {
     return NS_EnsureSafeToReturn(mJARFile, uri);
 }
 
--- a/modules/libjar/test/Makefile.in
+++ b/modules/libjar/test/Makefile.in
@@ -42,9 +42,13 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= test_libjar
 
 XPCSHELL_TESTS = unit
 
+ifdef MOZ_MOCHITEST
+DIRS		+= mochitest
+endif
+
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/modules/libjar/test/mochitest/Makefile.in
@@ -0,0 +1,54 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = modules/libjar/test/mochitest
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+		test_bug403331.html    \
+		bug403331.zip          \
+		bug403331.zip^headers^ \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..48ba268ddf64eb967753b79e6e6a43d7f0578d5f
GIT binary patch
literal 239
zc$^FHW@Zs#U|`^2c->iSo^IK;EfUBp2VzbJQHGM#;u5`#lH8oo5KabWEmJ3V5Du+i
zVfe}@!eH7P$<<)M<MO|_>k{`DCd2YT;mjr6Hxw$Wqo?neyr(0ft6n6Ln#N?ZRb|Wh
z<I6k^_J|qORIIEKEO~P+%BRcJ;o4<Q|9eZm?nv=>{ww4BJo(|uUHeS_Jzxv)W@Hj)
o#^o$t1`uEb;w6nB7Lp@bA&v~KU|<OFW@Uq@V`Ojv(o?~@0CwR-D*ylh
new file mode 100644
--- /dev/null
+++ b/modules/libjar/test/mochitest/bug403331.zip^headers^
@@ -0,0 +1,1 @@
+Content-Type: application/java-archive
new file mode 100644
--- /dev/null
+++ b/modules/libjar/test/mochitest/test_bug403331.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=403331
+-->
+<head>
+  <title>Test for Bug 403331</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<iframe id="testFrame"></iframe>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 403331 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+  var testFrame = document.getElementById('testFrame');
+
+  // Try a redirected load from another domain to this one.
+
+  testFrame.onload = function() {
+    // If properly redirected, we'll be able to access elements in the loaded
+    // document.
+    var item = testFrame.contentDocument.getElementById('testitem');
+    is(item.textContent, "testcontents", "Should be able to access the child document");
+
+    SimpleTest.finish();
+  }
+
+  testFrame.src = "jar:http://example.org:80/redirect?http://localhost:8888/tests/modules/libjar/test/mochitest/bug403331.zip!/test.html";
+}
+
+addLoadEvent(runTest);
+
+</script>
+</pre>
+
+</body>
+</html>
--- a/testing/mochitest/server.js
+++ b/testing/mochitest/server.js
@@ -135,16 +135,18 @@ function runServer()
   serverBasePath.append("testing");
   serverBasePath.append("mochitest");
   server = new nsHttpServer();
   server.registerDirectory("/", serverBasePath);
 
   if (environment["CLOSE_WHEN_DONE"])
     server.registerPathHandler("/server/shutdown", serverShutdown);
 
+  server.registerPathHandler("/redirect", redirect);
+
   server.setIndexHandler(defaultDirHandler);
   server.start(SERVER_PORT);
 
   // touch a file in the profile directory to indicate we're alive
   var foStream = Cc["@mozilla.org/network/file-output-stream;1"]
                    .createInstance(Ci.nsIFileOutputStream);
   var serverAlive = Cc["@mozilla.org/file/local;1"]
                       .createInstance(Ci.nsILocalFile);
@@ -193,16 +195,22 @@ function serverShutdown(metadata, respon
   var body = "Server shut down.";
   response.bodyOutputStream.write(body, body.length);
 
   // Note: this doesn't disrupt the current request.
   server.stop();
   otherDomainServer.stop();
 }
 
+function redirect(metadata, response)
+{
+  response.setStatusLine("1.1", 301, "Moved Permanently");
+  response.setHeader("Location", metadata.queryString);
+}
+
 //
 // DIRECTORY LISTINGS
 //
 
 /**
  * Creates a generator that iterates over the contents of
  * an nsIFile directory.
  */