On browser close, the browser checks to see if there are any pending downloads.

Currently: If there are any pending downloads, it halts the download and asks the user to keep or save the download.

New behavior: The user won't be prompted for pending downloads that are malicious (DANGEROUS_HOST, DANGEROUS_URL, DANGEROUS_CONTENT). Instead, they'll just be automatically cleaned up on exit. Note that if a user is prompted for *other* downloads, they may still be taken to the chrome://downloads page and see the malicious download while they're there.
Added a new test in chrome/browser/lifetime/browser_close_manager_browsertest.cc.

BUG=306230, 305387
TEST=
1. Download a malicious file (e.g., http://download.safebrowsingtest.com/download/test)
2. Quit the browser
3. The browser should close without a warning
4. Download a dangerous file like a SWF
5. Quit the browser
6. The browser should pop up a dialog asking you whether you should save the file

[email protected], [email protected], [email protected], [email protected], [email protected]

Review URL: https://codereview.chromium.org/26938003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229784 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/lifetime/browser_close_manager_browsertest.cc b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
index ce61b24..3023e55 100644
--- a/chrome/browser/lifetime/browser_close_manager_browsertest.cc
+++ b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
@@ -8,6 +8,9 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/download/chrome_download_manager_delegate.h"
+#include "chrome/browser/download/download_service.h"
+#include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/lifetime/browser_close_manager.h"
 #include "chrome/browser/net/url_request_mock_util.h"
@@ -31,6 +34,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/download_test_observer.h"
 #include "content/public/test/test_navigation_observer.h"
+#include "content/test/net/url_request_mock_http_job.h"
 #include "content/test/net/url_request_slow_download_job.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
@@ -121,6 +125,7 @@
   enum UserChoice {
     USER_CHOICE_USER_CANCELS_CLOSE,
     USER_CHOICE_USER_ALLOWS_CLOSE,
+    NO_USER_CHOICE
   };
 
   static void AttemptClose(UserChoice user_choice) {
@@ -135,7 +140,9 @@
   virtual void ConfirmCloseWithPendingDownloads(
       int download_count,
       const base::Callback<void(bool)>& callback) OVERRIDE {
+    EXPECT_NE(NO_USER_CHOICE, user_choice_);
     switch (user_choice_) {
+      case NO_USER_CHOICE:
       case USER_CHOICE_USER_CANCELS_CLOSE: {
         callback.Run(false);
         break;
@@ -156,6 +163,38 @@
   DISALLOW_COPY_AND_ASSIGN(TestBrowserCloseManager);
 };
 
+class TestDownloadManagerDelegate : public ChromeDownloadManagerDelegate {
+ public:
+  explicit TestDownloadManagerDelegate(Profile* profile)
+      : ChromeDownloadManagerDelegate(profile) {
+    SetNextId(content::DownloadItem::kInvalidId + 1);
+  }
+
+  virtual bool DetermineDownloadTarget(
+      content::DownloadItem* item,
+      const content::DownloadTargetCallback& callback) OVERRIDE {
+    content::DownloadTargetCallback dangerous_callback =
+        base::Bind(&TestDownloadManagerDelegate::SetDangerous, this, callback);
+    return ChromeDownloadManagerDelegate::DetermineDownloadTarget(
+        item, dangerous_callback);
+  }
+
+  void SetDangerous(
+      const content::DownloadTargetCallback& callback,
+      const base::FilePath& target_path,
+      content::DownloadItem::TargetDisposition disp,
+      content::DownloadDangerType danger_type,
+      const base::FilePath& intermediate_path) {
+    callback.Run(target_path,
+                 disp,
+                 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
+                 intermediate_path);
+  }
+
+ private:
+  virtual ~TestDownloadManagerDelegate() {}
+};
+
 }  // namespace
 
 class BrowserCloseManagerBrowserTest
@@ -619,6 +658,49 @@
   EXPECT_TRUE(chrome::BrowserIterator().done());
 }
 
+// Test shutdown with a DANGEROUS_URL download undecided.
+IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest,
+    TestWithDangerousUrlDownload) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+  // Set up the fake delegate that forces the download to be malicious.
+  scoped_refptr<TestDownloadManagerDelegate> test_delegate(
+      new TestDownloadManagerDelegate(browser()->profile()));
+  DownloadServiceFactory::GetForBrowserContext(browser()->profile())->
+      SetDownloadManagerDelegateForTesting(test_delegate.get());
+
+  // Run a dangerous download, but the user doesn't make a decision.
+  // This .swf normally would be categorized as DANGEROUS_FILE, but
+  // TestDownloadManagerDelegate turns it into DANGEROUS_URL.
+  base::FilePath file(FILE_PATH_LITERAL("downloads/dangerous/dangerous.swf"));
+  GURL download_url(content::URLRequestMockHTTPJob::GetMockUrl(file));
+  content::DownloadTestObserverInterrupted observer(
+      content::BrowserContext::GetDownloadManager(browser()->profile()),
+      1,
+      content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_QUIT);
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(),
+      GURL(download_url),
+      NEW_BACKGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_NONE);
+  observer.WaitForFinished();
+
+  // Check that the download manager has the expected state.
+  EXPECT_EQ(1, content::BrowserContext::GetDownloadManager(
+      browser()->profile())->InProgressCount());
+  EXPECT_EQ(0, content::BrowserContext::GetDownloadManager(
+      browser()->profile())->NonMaliciousInProgressCount());
+
+  // Close the browser with no user action.
+  RepeatedNotificationObserver close_observer(
+      chrome::NOTIFICATION_BROWSER_CLOSED, 1);
+  TestBrowserCloseManager::AttemptClose(
+      TestBrowserCloseManager::NO_USER_CHOICE);
+  close_observer.Wait();
+  EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
+  EXPECT_TRUE(chrome::BrowserIterator().done());
+}
+
 // Test shutdown with a download in progress.
 IN_PROC_BROWSER_TEST_P(BrowserCloseManagerBrowserTest, TestWithDownloads) {
   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());