backing out patch for bug 299372 for b4, as per bug 420481
authorvladimir@pobox.com
Sun, 02 Mar 2008 23:31:37 -0800
changeset 12501 2013c0d48e472cca898ed5a982a1d6bb53d464e8
parent 12500 6ee3e50786dc00c71312abc91f1cbf2e187b7fa5
child 12502 28646ddf8d1f0060c1da42f8b99943d0a71bb2aa
push idunknown
push userunknown
push dateunknown
bugs299372, 420481
milestone1.9b4pre
backing out patch for bug 299372 for b4, as per bug 420481
browser/app/profile/firefox.js
browser/base/content/nsContextMenu.js
uriloader/base/nsURILoader.cpp
uriloader/base/nsURILoader.h
uriloader/exthandler/nsExternalHelperAppService.cpp
uriloader/exthandler/nsExternalHelperAppService.h
uriloader/exthandler/nsIExternalHelperAppService.idl
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -216,22 +216,16 @@ pref("browser.urlbar.filter.javascript",
 // the maximum number of results to show in autocomplete when doing richResults
 pref("browser.urlbar.maxRichResults", 25);
 // Size of "chunks" affects the number of places to process between each search
 // timeout (ms). Too big and the UI will be unresponsive; too small and we'll
 // be waiting on the timeout too often without many results.
 pref("browser.urlbar.search.chunkSize", 1000);
 pref("browser.urlbar.search.timeout", 50);
 
-// Number of milliseconds to wait for the http headers (and thus
-// the Content-Disposition filename) before giving up and falling back to 
-// picking a filename without that info in hand so that the user sees some
-// feedback from their action.
-pref("browser.download.saveLinkAsFilenameTimeout", 1000);
-
 pref("browser.download.useDownloadDir", true);
 pref("browser.download.folderList", 0);
 pref("browser.download.manager.showAlertOnComplete", true);
 pref("browser.download.manager.showAlertInterval", 2000);
 pref("browser.download.manager.retention", 2);
 pref("browser.download.manager.showWhenStarting", true);
 pref("browser.download.manager.useWindow", true);
 pref("browser.download.manager.closeWhenDone", false);
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -36,17 +36,16 @@
 #   Tom Germeau <tom.germeau@epigoon.com>
 #   Jesse Ruderman <jruderman@gmail.com>
 #   Joe Hughes <joe@retrovirus.com>
 #   Pamela Greene <pamg.bugs@gmail.com>
 #   Michael Ventnor <ventnors_dogs234@yahoo.com.au>
 #   Simon B├╝nzli <zeniko@gmail.com>
 #   Gijs Kruitbosch <gijskruitbosch@gmail.com>
 #   Ehsan Akhgari <ehsan.akhgari@gmail.com>
-#   Dan Mosedale <dmose@mozilla.org>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either 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
@@ -822,132 +821,20 @@ nsContextMenu.prototype = {
 
   // Save URL of clicked-on frame.
   saveFrame: function () {
     saveDocument(this.target.ownerDocument);
   },
 
   // Save URL of clicked-on link.
   saveLink: function() {
-    // canonical def in nsURILoader.h
-    const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020;
-    
     var doc =  this.target.ownerDocument;
     urlSecurityCheck(this.linkURL, doc.nodePrincipal);
-    var linkText = this.linkText();
-    var linkURL = this.linkURL;
-
-
-    // an object to proxy the data through to
-    // nsIExternalHelperAppService.doContent, which will wait for the
-    // appropriate MIME-type headers and then prompt the user with a
-    // file picker
-    function saveAsListener() {}
-    saveAsListener.prototype = {
-      extListener: null, 
-
-      onStartRequest: function saveLinkAs_onStartRequest(aRequest, aContext) {
-
-        // if the timer fired, the error status will have been caused by that,
-        // and we'll be restarting in onStopRequest, so no reason to notify
-        // the user
-        if (aRequest.status == NS_ERROR_SAVE_LINK_AS_TIMEOUT)
-          return;
-
-        timer.cancel();
-
-        // some other error occured; notify the user...
-        if (!Components.isSuccessCode(aRequest.status)) {
-          try {
-            const sbs = Cc["@mozilla.org/intl/stringbundle;1"].
-                        getService(Ci.nsIStringBundleService);
-            const bundle = sbs.createBundle(
-                    "chrome://mozapps/locale/downloads/downloads.properties");
-            
-            const title = bundle.GetStringFromName("downloadErrorAlertTitle");
-            const msg = bundle.GetStringFromName("downloadErrorGeneric");
-            
-            const promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"].
-                              getService(Ci.nsIPromptService);
-            promptSvc.alert(doc.defaultView, title, msg);
-          } catch (ex) {}
-          return;
-        }
-
-        var extHelperAppSvc = 
-          Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
-          getService(Ci.nsIExternalHelperAppService);
-        this.extListener = 
-          extHelperAppSvc.doContent(aRequest.contentType, aRequest, 
-                                    doc.defaultView, true);
-        this.extListener.onStartRequest(aRequest, aContext);
-      }, 
-
-      onStopRequest: function saveLinkAs_onStopRequest(aRequest, aContext, 
-                                                       aStatusCode) {
-        if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) {
-          // do it the old fashioned way, which will pick the best filename
-          // it can without waiting.
-          saveURL(linkURL, linkText, null, true, false, doc.documentURIObject);
-        }
-        if (this.extListener)
-          this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
-      },
-       
-      onDataAvailable: function saveLinkAs_onDataAvailable(aRequest, aContext,
-                                                           aInputStream,
-                                                           aOffset, aCount) {
-        this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
-                                         aOffset, aCount);
-      }
-    }
-
-    // in case we need to prompt the user for authentication
-    function callbacks() {}
-    callbacks.prototype = {
-      getInterface: function sLA_callbacks_getInterface(aIID) {
-        if (aIID.equals(Ci.nsIAuthPrompt) || aIID.equals(Ci.nsIAuthPrompt2)) {
-          var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-                   getService(Ci.nsIPromptFactory);
-          return ww.getPrompt(doc.defaultView, aIID);
-        }
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      } 
-    }
-
-    // if it we don't have the headers after a short time, the user 
-    // won't have received any feedback from their click.  that's bad.  so
-    // we give up waiting for the filename. 
-    function timerCallback() {}
-    timerCallback.prototype = {
-      notify: function sLA_timer_notify(aTimer) {
-        channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
-        return;
-      }
-    }
-
-    // set up a channel to do the saving
-    var ioService = Cc["@mozilla.org/network/io-service;1"].
-                    getService(Ci.nsIIOService);
-    var channel = ioService.newChannelFromURI(this.getLinkURI());
-    channel.notificationCallbacks = new callbacks();
-    channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE |
-                         Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
-    if (channel instanceof Ci.nsIHttpChannel)
-      channel.referrer = doc.documentURIObject;
-
-    // fallback to the old way if we don't see the headers quickly 
-    var timeToWait = 
-      gPrefService.getIntPref("browser.download.saveLinkAsFilenameTimeout");
-    var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-    timer.initWithCallback(new timerCallback(), timeToWait,
-                           timer.TYPE_ONE_SHOT);
-
-    // kick off the channel with our proxy object as the listener
-    channel.asyncOpen(new saveAsListener(), null);
+    saveURL(this.linkURL, this.linkText(), null, true, false,
+            doc.documentURIObject);
   },
 
   sendLink: function() {
     // we don't know the title of the link so pass in an empty string
     MailIntegration.sendMessage( this.linkURL, "" );
   },
 
   // Save URL of clicked-on image.
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -589,17 +589,16 @@ nsresult nsDocumentOpenInfo::DispatchCon
     if (isGuessFromExt) {
       mContentType = APPLICATION_GUESS_FROM_EXT;
       aChannel->SetContentType(NS_LITERAL_CSTRING(APPLICATION_GUESS_FROM_EXT));
     }
 
     rv = helperAppService->DoContent(mContentType,
                                      request,
                                      m_originalContext,
-                                     PR_FALSE,
                                      getter_AddRefs(m_targetStreamListener));
     if (NS_FAILED(rv)) {
       request->SetLoadFlags(loadFlags);
       m_targetStreamListener = nsnull;
     }
   }
       
   NS_ASSERTION(m_targetStreamListener || NS_FAILED(rv),
--- a/uriloader/base/nsURILoader.h
+++ b/uriloader/base/nsURILoader.h
@@ -94,15 +94,9 @@ protected:
 
 /**
  * The load has been cancelled because it was found on a malware or phishing blacklist.
  * XXX: this belongs in an nsDocShellErrors.h file of some sort.
  */
 #define NS_ERROR_MALWARE_URI   NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_URILOADER, 30)
 #define NS_ERROR_PHISHING_URI  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_URILOADER, 31)
 
-/**
- * Used when "Save Link As..." doesn't see the headers quickly enough to choose
- * a filename.  See nsContextMenu.js. 
- */
-#define NS_ERROR_SAVE_LINK_AS_TIMEOUT  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_URILOADER, 32);
-
 #endif /* nsURILoader_h__ */
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -519,17 +519,16 @@ nsresult nsExternalHelperAppService::Ini
 nsExternalHelperAppService::~nsExternalHelperAppService()
 {
   gExtProtSvc = nsnull;
 }
 
 NS_IMETHODIMP nsExternalHelperAppService::DoContent(const nsACString& aMimeContentType,
                                                     nsIRequest *aRequest,
                                                     nsIInterfaceRequestor *aWindowContext,
-                                                    PRBool aForceSave,
                                                     nsIStreamListener ** aStreamListener)
 {
   nsAutoString fileName;
   nsCAutoString fileExtension;
   PRUint32 reason = nsIHelperAppLauncherDialog::REASON_CANTHANDLE;
   nsresult rv;
 
   // Get the file extension and name that we will need later
@@ -636,18 +635,17 @@ NS_IMETHODIMP nsExternalHelperAppService
   // nsExternalAppHandler
   nsCAutoString buf;
   mimeInfo->GetPrimaryExtension(buf);
 
   nsExternalAppHandler * handler = new nsExternalAppHandler(mimeInfo,
                                                             buf,
                                                             aWindowContext,
                                                             fileName,
-                                                            reason,
-                                                            aForceSave);
+                                                            reason);
   if (!handler)
     return NS_ERROR_OUT_OF_MEMORY;
   NS_ADDREF(*aStreamListener = handler);
   
   return NS_OK;
 }
 
 NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension(const nsACString& aExtension,
@@ -988,22 +986,21 @@ NS_INTERFACE_MAP_BEGIN(nsExternalAppHand
    NS_INTERFACE_MAP_ENTRY(nsICancelable)
    NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
 NS_INTERFACE_MAP_END_THREADSAFE
 
 nsExternalAppHandler::nsExternalAppHandler(nsIMIMEInfo * aMIMEInfo,
                                            const nsCSubstring& aTempFileExtension,
                                            nsIInterfaceRequestor* aWindowContext,
                                            const nsAString& aSuggestedFilename,
-                                           PRUint32 aReason, PRBool aForceSave)
+                                           PRUint32 aReason)
 : mMimeInfo(aMIMEInfo)
 , mWindowContext(aWindowContext)
 , mWindowToClose(nsnull)
 , mSuggestedFileName(aSuggestedFilename)
-, mForceSave(aForceSave)
 , mCanceled(PR_FALSE)
 , mShouldCloseWindow(PR_FALSE)
 , mReceivedDispositionInfo(PR_FALSE)
 , mStopRequestIssued(PR_FALSE)
 , mProgressListenerInitialized(PR_FALSE)
 , mReason(aReason)
 , mContentLength(-1)
 , mProgress(0)
@@ -1468,23 +1465,16 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
 
   // OK, now check why we're here
   if (!alwaysAsk && mReason != nsIHelperAppLauncherDialog::REASON_CANTHANDLE) {
     // Force asking if we're not saving.  See comment back when we fetched the
     // alwaysAsk boolean for details.
     alwaysAsk = (action != nsIMIMEInfo::saveToDisk);
   }
 
-  // if we were told that we _must_ save to disk without asking, all the stuff
-  // before this is irrelevant; override it
-  if (mForceSave) {
-    alwaysAsk = PR_FALSE;
-    action = nsIMIMEInfo::saveToDisk;
-  }
-  
   if (alwaysAsk)
   {
     // do this first! make sure we don't try to take an action until the user tells us what they want to do
     // with it...
     mReceivedDispositionInfo = PR_FALSE; 
 
     // invoke the dialog!!!!! use mWindowContext as the window context parameter for the dialog request
     mDialog = do_CreateInstance( NS_IHELPERAPPLAUNCHERDLG_CONTRACTID, &rv );
--- a/uriloader/exthandler/nsExternalHelperAppService.h
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
@@ -246,17 +246,17 @@ public:
    * @param aWindowContext Window context, as passed to DoContent
    * @param aFileName      The filename to use
    * @param aReason        A constant from nsIHelperAppLauncherDialog indicating
    *                       why the request is handled by a helper app.
    */
   nsExternalAppHandler(nsIMIMEInfo * aMIMEInfo, const nsCSubstring& aFileExtension,
                        nsIInterfaceRequestor * aWindowContext,
                        const nsAString& aFilename,
-                       PRUint32 aReason, PRBool aForceSave);
+                       PRUint32 aReason);
 
   ~nsExternalAppHandler();
 
 protected:
   nsCOMPtr<nsIFile> mTempFile;
   nsCOMPtr<nsIURI> mSourceUrl;
   nsString mTempFileExtension;
   /**
@@ -276,23 +276,16 @@ protected:
   /**
    * The following field is set if we were processing an http channel that had
    * a content disposition header which specified the SUGGESTED file name we
    * should present to the user in the save to disk dialog. 
    */
   nsString mSuggestedFileName;
 
   /**
-   * If set, this handler should forcibly save the file to disk regardless of
-   * MIME info settings or anything else, without ever popping up the 
-   * unknown content type handling dialog.
-   */
-  PRPackedBool mForceSave;
-  
-  /**
    * The canceled flag is set if the user canceled the launching of this
    * application before we finished saving the data to a temp file.
    */
   PRPackedBool mCanceled;
 
   /**
    * This is set based on whether the channel indicates that a new window
    * was opened specifically for this download.  If so, then we
--- a/uriloader/exthandler/nsIExternalHelperAppService.idl
+++ b/uriloader/exthandler/nsIExternalHelperAppService.idl
@@ -46,36 +46,33 @@ interface nsIFile;
 interface nsIMIMEInfo;
 interface nsIWebProgressListener2;
 interface nsIInterfaceRequestor;
 
 /**
  * The external helper app service is used for finding and launching
  * platform specific external applications for a given mime content type.
  */
-[scriptable, uuid(9e456297-ba3e-42b1-92bd-b7db014268cb)]
+[scriptable, uuid(0ea90cf3-2dd9-470f-8f76-f141743c5678)]
 interface nsIExternalHelperAppService : nsISupports
 {
   /**
    * Binds an external helper application to a stream listener. The caller
    * should pump data into the returned stream listener. When the OnStopRequest
    * is issued, the stream listener implementation will launch the helper app
    * with this data.
    * @param aMimeContentType The content type of the incoming data
    * @param aRequest The request corresponding to the incoming data
    * @param aWindowContext Use GetInterface to retrieve properties like the
    *                       dom window or parent window...
    *                       The service might need this in order to bring up dialogs.
-   * @param aForceSave True to always save this content to disk, regardless of
-   *                   nsIMIMEInfo and other such influences.
    * @return A nsIStreamListener which the caller should pump the data into.
    */
   nsIStreamListener doContent (in ACString aMimeContentType, in nsIRequest aRequest,
-                               in nsIInterfaceRequestor aWindowContext,
-                               in boolean aForceSave); 
+                               in nsIInterfaceRequestor aWindowContext); 
 
   /**
    * Returns true if data from a URL with this extension combination
    * is to be decoded from aEncodingType prior to saving or passing
    * off to helper apps, false otherwise.
    */
   boolean applyDecodingForExtension(in AUTF8String aExtension,
                                     in ACString aEncodingType);