Bug 948029 - [Download API] Downloading resources isn't driven by user consent. r=bz
authorGhislain 'Aus' Lacroix <glacroix@mozilla.com>
Fri, 14 Mar 2014 14:24:23 -0700
changeset 190834 df384c7c679a925ea328b43cc1c1c27b37bd4bff
parent 190833 e09f4b94cf29e637326767738cb7727975707b35
child 190835 c0d3b916acfbde058e7028b3ee69ecf59cf2d17a
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs948029
milestone30.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 948029 - [Download API] Downloading resources isn't driven by user consent. r=bz
b2g/app/b2g.js
uriloader/base/nsURILoader.cpp
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -855,16 +855,25 @@ pref("b2g.neterror.url", "app://system.g
 
 // Enable Web Speech synthesis API
 pref("media.webspeech.synth.enabled", true);
 
 // Downloads API
 pref("dom.mozDownloads.enabled", true);
 pref("dom.downloads.max_retention_days", 7);
 
+// External Helper Application Handling
+//
+// All external helper application handling can require the docshell to be
+// active before allowing the external helper app service to handle content.
+//
+// To prevent SD card DoS attacks via downloads we disable background handling.
+//
+pref("security.exthelperapp.disable_background_handling", true);
+
 // Inactivity time in milliseconds after which we shut down the OS.File worker.
 pref("osfile.reset_worker_delay", 5000);
 
 // APZC preferences.
 //
 // Gaia relies heavily on scroll events for now, so lets fire them
 // more often than the default value (100).
 pref("apz.asyncscroll.throttle", 40);
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -44,25 +44,29 @@
 
 #include "nsIMIMEHeaderParam.h"
 #include "nsNetCID.h"
 
 #include "nsMimeTypes.h"
 
 #include "nsDocLoader.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Preferences.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* nsURILoader::mLog = nullptr;
 #endif
 
 #define LOG(args) PR_LOG(nsURILoader::mLog, PR_LOG_DEBUG, args)
 #define LOG_ERROR(args) PR_LOG(nsURILoader::mLog, PR_LOG_ERROR, args)
 #define LOG_ENABLED() PR_LOG_TEST(nsURILoader::mLog, PR_LOG_DEBUG)
 
+#define NS_PREF_DISABLE_BACKGROUND_HANDLING \
+    "security.exthelperapp.disable_background_handling"
+
 /**
  * The nsDocumentOpenInfo contains the state required when a single
  * document is being opened in order to discover the content type...
  * Each instance remains alive until its target URL has been loaded
  * (or aborted).
  */
 class nsDocumentOpenInfo MOZ_FINAL : public nsIStreamListener
                                    , public nsIThreadRetargetableStreamListener
@@ -514,16 +518,45 @@ nsresult nsDocumentOpenInfo::DispatchCon
     }
   }
   
   // Sixth step:
   //
   // All attempts to dispatch this content have failed.  Just pass it off to
   // the helper app service.
   //
+
+  //
+  // Optionally, we may want to disable background handling by the external
+  // helper application service.
+  //
+  if (mozilla::Preferences::GetBool(NS_PREF_DISABLE_BACKGROUND_HANDLING,
+                                    false)) {
+    // First, we will ensure that the parent docshell is in an active
+    // state as we will disallow all external application handling unless it is
+    // in the foreground.
+    nsCOMPtr<nsIDocShell> docShell(do_GetInterface(m_originalContext));
+    if (!docShell) {
+      // If we can't perform our security check we definitely don't want to go
+      // any further!
+      LOG(("Failed to get DocShell to ensure it is active before anding off to "
+           "helper app service. Aborting."));
+      return NS_ERROR_FAILURE;
+    }
+
+    // Ensure the DocShell is active before continuing.
+    bool isActive = false;
+    docShell->GetIsActive(&isActive);
+    if (!isActive) {
+      LOG(("  Check for active DocShell returned false. Aborting hand off to "
+           "helper app service."));
+      return NS_ERROR_DOM_SECURITY_ERR;
+    }
+  }
+
   nsCOMPtr<nsIExternalHelperAppService> helperAppService =
     do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID, &rv);
   if (helperAppService) {
     LOG(("  Passing load off to helper app service"));
 
     // Set these flags to indicate that the channel has been targeted and that
     // we are not using the original consumer.
     nsLoadFlags loadFlags = 0;