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 id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
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);