Bug 818559 - Don't ask to unload if we know we're going to download. r=smaug
authorBenjamin Peterson <benjamin@python.org>
Fri, 07 Dec 2012 20:35:17 -0500
changeset 124608 af0f5575a15324cb76c3d9c77b7f5ac18c5da8f6
parent 124607 40324fd7e5db82bb1aec5341832e4f015b163707
child 124609 ab7c54f6472f52cf91e81320c5f404cccbcbe526
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs818559
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 818559 - Don't ask to unload if we know we're going to download. r=smaug
browser/base/content/test/browser_bug676619.js
browser/base/content/test/download_page.html
docshell/base/nsDocShell.cpp
dom/src/jsurl/nsJSProtocolHandler.cpp
--- a/browser/base/content/test/browser_bug676619.js
+++ b/browser/base/content/test/browser_bug676619.js
@@ -18,16 +18,17 @@ function test () {
         next();
       });
 
       doc.getElementById(link).click();
     }
 
     function testLink(link, name, next) {
         addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function (win) {
+            is(doc.getElementById("unload-flag").textContent, "Okay", "beforeunload shouldn't have fired");
             is(win.document.getElementById("location").value, name, "file name should match");
             win.close();
             next();
         });
 
         doc.getElementById(link).click();
     }
 
@@ -112,9 +113,9 @@ TabOpenListener.prototype = {
       this.opencallback = null;
       this.tab = null;
       this.browser = null;
       // Let the window close complete
       executeSoon(this.closecallback);
       this.closecallback = null;
     }
   }
-};
\ No newline at end of file
+};
--- a/browser/base/content/test/download_page.html
+++ b/browser/base/content/test/download_page.html
@@ -28,15 +28,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 
         a.href = window.URL.createObjectURL(new Blob(["just text"]))    ;
         a.download = "test.blob";
         a.id = "link6";
         a.textContent = 'Download "test.blob"';
 
         li.appendChild(a);
         document.getElementsByTagName('ul')[0].appendChild(li);
+
+        window.addEventListener("beforeunload", function (evt) {
+            document.getElementById("unload-flag").textContent = "Fail";
+        });
     </script>
     <ul>
         <li><a href="http://example.com/"
                 download="example.com" id="link7" target="_blank">Download "example.com"</a></li>
     <ul>
+    <div id="unload-flag">Okay</div>
   </body>
 </html>
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -8977,33 +8977,34 @@ nsDocShell::InternalLoad(nsIURI * aURI,
     // XXXbz mTiming should know what channel it's for, so we don't
     // need this hackery.  Note that this is still broken in cases
     // when we're loading something that's not javascript: and the
     // beforeunload handler denies the load.  That will screw up
     // timing for the next load!
     if (!bIsJavascript) {
         MaybeInitTiming();
     }
-    if (mTiming) {
+    bool timeBeforeUnload = mTiming && aFileName.IsVoid();
+    if (timeBeforeUnload) {
       mTiming->NotifyBeforeUnload();
     }
     // Check if the page doesn't want to be unloaded. The javascript:
     // protocol handler deals with this for javascript: URLs.
-    if (!bIsJavascript && mContentViewer) {
+    if (!bIsJavascript && aFileName.IsVoid() && mContentViewer) {
         bool okToUnload;
         rv = mContentViewer->PermitUnload(false, &okToUnload);
 
         if (NS_SUCCEEDED(rv) && !okToUnload) {
             // The user chose not to unload the page, interrupt the
             // load.
             return NS_OK;
         }
     }
 
-    if (mTiming) {
+    if (timeBeforeUnload) {
       mTiming->NotifyUnloadAccepted(mCurrentURI);
     }
 
     // Check for saving the presentation here, before calling Stop().
     // This is necessary so that we can catch any pending requests.
     // Since the new request has not been created yet, we pass null for the
     // new request parameter.
     // Also pass nullptr for the document, since it doesn't affect the return
--- a/dom/src/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/src/jsurl/nsJSProtocolHandler.cpp
@@ -780,20 +780,23 @@ nsJSChannel::EvaluateScript()
     // EvaluateScript() succeeded, and we were not canceled, that
     // means there's data to parse as a result of evaluating the
     // script.
 
     // Get the stream channels load flags (!= mLoadFlags).
     nsLoadFlags loadFlags;
     mStreamChannel->GetLoadFlags(&loadFlags);
 
-    if (loadFlags & LOAD_DOCUMENT_URI) {
-        // We're loaded as the document channel. If we go on,
-        // we'll blow away the current document. Make sure that's
-        // ok. If so, stop all pending network loads.
+    uint32_t disposition;
+    if (NS_FAILED(mStreamChannel->GetContentDisposition(&disposition)))
+        disposition = nsIChannel::DISPOSITION_INLINE;
+    if (loadFlags & LOAD_DOCUMENT_URI && disposition != nsIChannel::DISPOSITION_ATTACHMENT) {
+        // We're loaded as the document channel and not expecting to download
+        // the result. If we go on, we'll blow away the current document. Make
+        // sure that's ok. If so, stop all pending network loads.
 
         nsCOMPtr<nsIDocShell> docShell;
         NS_QueryNotificationCallbacks(mStreamChannel, docShell);
         if (docShell) {
             nsCOMPtr<nsIContentViewer> cv;
             docShell->GetContentViewer(getter_AddRefs(cv));
 
             if (cv) {