• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/files/file_path.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/path_service.h"
12 #include "base/prefs/pref_member.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/test/test_file_util.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/browser/download/chrome_download_manager_delegate.h"
17 #include "chrome/browser/download/download_history.h"
18 #include "chrome/browser/download/download_prefs.h"
19 #include "chrome/browser/download/download_service.h"
20 #include "chrome/browser/download/download_service_factory.h"
21 #include "chrome/browser/download/save_package_file_picker.h"
22 #include "chrome/browser/history/download_row.h"
23 #include "chrome/browser/net/url_request_mock_util.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/browser_commands.h"
27 #include "chrome/browser/ui/browser_window.h"
28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
29 #include "chrome/common/chrome_paths.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/common/url_constants.h"
33 #include "chrome/test/base/in_process_browser_test.h"
34 #include "chrome/test/base/ui_test_utils.h"
35 #include "content/public/browser/download_item.h"
36 #include "content/public/browser/download_manager.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/browser/notification_types.h"
39 #include "content/public/browser/web_contents.h"
40 #include "content/public/test/test_utils.h"
41 #include "content/test/net/url_request_mock_http_job.h"
42 #include "testing/gtest/include/gtest/gtest.h"
43 
44 using content::BrowserContext;
45 using content::BrowserThread;
46 using content::DownloadItem;
47 using content::DownloadManager;
48 using content::URLRequestMockHTTPJob;
49 using content::WebContents;
50 
51 namespace {
52 
53 // Waits for an item record in the downloads database to match |filter|. See
54 // DownloadStoredProperly() below for an example filter.
55 class DownloadPersistedObserver : public DownloadHistory::Observer {
56  public:
57   typedef base::Callback<bool(
58       DownloadItem* item,
59       const history::DownloadRow&)> PersistedFilter;
60 
DownloadPersistedObserver(Profile * profile,const PersistedFilter & filter)61   DownloadPersistedObserver(Profile* profile, const PersistedFilter& filter)
62     : profile_(profile),
63       filter_(filter),
64       waiting_(false),
65       persisted_(false) {
66     DownloadServiceFactory::GetForBrowserContext(profile_)->
67       GetDownloadHistory()->AddObserver(this);
68   }
69 
~DownloadPersistedObserver()70   virtual ~DownloadPersistedObserver() {
71     DownloadService* service = DownloadServiceFactory::GetForBrowserContext(
72         profile_);
73     if (service && service->GetDownloadHistory())
74       service->GetDownloadHistory()->RemoveObserver(this);
75   }
76 
WaitForPersisted()77   bool WaitForPersisted() {
78     if (persisted_)
79       return true;
80     waiting_ = true;
81     content::RunMessageLoop();
82     waiting_ = false;
83     return persisted_;
84   }
85 
OnDownloadStored(DownloadItem * item,const history::DownloadRow & info)86   virtual void OnDownloadStored(DownloadItem* item,
87                                 const history::DownloadRow& info) OVERRIDE {
88     persisted_ = persisted_ || filter_.Run(item, info);
89     if (persisted_ && waiting_)
90       base::MessageLoopForUI::current()->Quit();
91   }
92 
93  private:
94   Profile* profile_;
95   DownloadItem* item_;
96   PersistedFilter filter_;
97   bool waiting_;
98   bool persisted_;
99 
100   DISALLOW_COPY_AND_ASSIGN(DownloadPersistedObserver);
101 };
102 
103 // Waits for an item record to be removed from the downloads database.
104 class DownloadRemovedObserver : public DownloadPersistedObserver {
105  public:
DownloadRemovedObserver(Profile * profile,int32 download_id)106   DownloadRemovedObserver(Profile* profile, int32 download_id)
107       : DownloadPersistedObserver(profile, PersistedFilter()),
108         removed_(false),
109         waiting_(false),
110         download_id_(download_id) {
111   }
~DownloadRemovedObserver()112   virtual ~DownloadRemovedObserver() {}
113 
WaitForRemoved()114   bool WaitForRemoved() {
115     if (removed_)
116       return true;
117     waiting_ = true;
118     content::RunMessageLoop();
119     waiting_ = false;
120     return removed_;
121   }
122 
OnDownloadStored(DownloadItem * item,const history::DownloadRow & info)123   virtual void OnDownloadStored(DownloadItem* item,
124                                 const history::DownloadRow& info) OVERRIDE {
125   }
126 
OnDownloadsRemoved(const DownloadHistory::IdSet & ids)127   virtual void OnDownloadsRemoved(const DownloadHistory::IdSet& ids) OVERRIDE {
128     removed_ = ids.find(download_id_) != ids.end();
129     if (removed_ && waiting_)
130       base::MessageLoopForUI::current()->Quit();
131   }
132 
133  private:
134   bool removed_;
135   bool waiting_;
136   int32 download_id_;
137 
138   DISALLOW_COPY_AND_ASSIGN(DownloadRemovedObserver);
139 };
140 
DownloadStoredProperly(const GURL & expected_url,const base::FilePath & expected_path,int64 num_files,DownloadItem::DownloadState expected_state,DownloadItem * item,const history::DownloadRow & info)141 bool DownloadStoredProperly(
142     const GURL& expected_url,
143     const base::FilePath& expected_path,
144     int64 num_files,
145     DownloadItem::DownloadState expected_state,
146     DownloadItem* item,
147     const history::DownloadRow& info) {
148   // This function may be called multiple times for a given test. Returning
149   // false doesn't necessarily mean that the test has failed or will fail, it
150   // might just mean that the test hasn't passed yet.
151   if (info.target_path != expected_path) {
152     VLOG(20) << __FUNCTION__ << " " << info.target_path.value()
153              << " != " << expected_path.value();
154     return false;
155   }
156   if (info.url_chain.size() != 1u) {
157     VLOG(20) << __FUNCTION__ << " " << info.url_chain.size()
158              << " != 1";
159     return false;
160   }
161   if (info.url_chain[0] != expected_url) {
162     VLOG(20) << __FUNCTION__ << " " << info.url_chain[0].spec()
163              << " != " << expected_url.spec();
164     return false;
165   }
166   if ((num_files >= 0) && (info.received_bytes != num_files)) {
167     VLOG(20) << __FUNCTION__ << " " << num_files
168              << " != " << info.received_bytes;
169     return false;
170   }
171   if (info.state != expected_state) {
172     VLOG(20) << __FUNCTION__ << " " << info.state
173              << " != " << expected_state;
174     return false;
175   }
176   return true;
177 }
178 
179 const base::FilePath::CharType kTestDir[] = FILE_PATH_LITERAL("save_page");
180 
181 static const char kAppendedExtension[] =
182 #if defined(OS_WIN)
183     ".htm";
184 #else
185     ".html";
186 #endif
187 
188 // Loosely based on logic in DownloadTestObserver.
189 class DownloadItemCreatedObserver : public DownloadManager::Observer {
190  public:
DownloadItemCreatedObserver(DownloadManager * manager)191   explicit DownloadItemCreatedObserver(DownloadManager* manager)
192       : waiting_(false), manager_(manager) {
193     manager->AddObserver(this);
194   }
195 
~DownloadItemCreatedObserver()196   virtual ~DownloadItemCreatedObserver() {
197     if (manager_)
198       manager_->RemoveObserver(this);
199   }
200 
201   // Wait for the first download item created after object creation.
202   // Note that this class provides no protection against the download
203   // being destroyed between creation and return of WaitForNewDownloadItem();
204   // the caller must guarantee that in some other fashion.
WaitForDownloadItem(std::vector<DownloadItem * > * items_seen)205   void WaitForDownloadItem(std::vector<DownloadItem*>* items_seen) {
206     if (!manager_) {
207       // The manager went away before we were asked to wait; return
208       // what we have, even if it's null.
209       *items_seen = items_seen_;
210       return;
211     }
212 
213     if (items_seen_.empty()) {
214       waiting_ = true;
215       content::RunMessageLoop();
216       waiting_ = false;
217     }
218 
219     *items_seen = items_seen_;
220     return;
221   }
222 
223  private:
224   // DownloadManager::Observer
OnDownloadCreated(DownloadManager * manager,DownloadItem * item)225   virtual void OnDownloadCreated(
226       DownloadManager* manager, DownloadItem* item) OVERRIDE {
227     DCHECK_EQ(manager, manager_);
228     items_seen_.push_back(item);
229 
230     if (waiting_)
231       base::MessageLoopForUI::current()->Quit();
232   }
233 
ManagerGoingDown(DownloadManager * manager)234   virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
235     manager_->RemoveObserver(this);
236     manager_ = NULL;
237     if (waiting_)
238       base::MessageLoopForUI::current()->Quit();
239   }
240 
241   bool waiting_;
242   DownloadManager* manager_;
243   std::vector<DownloadItem*> items_seen_;
244 
245   DISALLOW_COPY_AND_ASSIGN(DownloadItemCreatedObserver);
246 };
247 
248 class SavePackageFinishedObserver : public content::DownloadManager::Observer {
249  public:
SavePackageFinishedObserver(content::DownloadManager * manager,const base::Closure & callback)250   SavePackageFinishedObserver(content::DownloadManager* manager,
251                               const base::Closure& callback)
252       : download_manager_(manager),
253         callback_(callback) {
254     download_manager_->AddObserver(this);
255   }
256 
~SavePackageFinishedObserver()257   virtual ~SavePackageFinishedObserver() {
258     if (download_manager_)
259       download_manager_->RemoveObserver(this);
260   }
261 
262   // DownloadManager::Observer:
OnSavePackageSuccessfullyFinished(content::DownloadManager * manager,content::DownloadItem * item)263   virtual void OnSavePackageSuccessfullyFinished(
264       content::DownloadManager* manager, content::DownloadItem* item) OVERRIDE {
265     callback_.Run();
266   }
ManagerGoingDown(content::DownloadManager * manager)267   virtual void ManagerGoingDown(content::DownloadManager* manager) OVERRIDE {
268     download_manager_->RemoveObserver(this);
269     download_manager_ = NULL;
270   }
271 
272  private:
273   content::DownloadManager* download_manager_;
274   base::Closure callback_;
275 
276   DISALLOW_COPY_AND_ASSIGN(SavePackageFinishedObserver);
277 };
278 
279 class SavePageBrowserTest : public InProcessBrowserTest {
280  public:
SavePageBrowserTest()281   SavePageBrowserTest() {}
282   virtual ~SavePageBrowserTest();
283 
284  protected:
SetUp()285   virtual void SetUp() OVERRIDE {
286     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir_));
287     ASSERT_TRUE(save_dir_.CreateUniqueTempDir());
288     InProcessBrowserTest::SetUp();
289   }
290 
SetUpOnMainThread()291   virtual void SetUpOnMainThread() OVERRIDE {
292     browser()->profile()->GetPrefs()->SetFilePath(
293         prefs::kDownloadDefaultDirectory, save_dir_.path());
294     browser()->profile()->GetPrefs()->SetFilePath(
295         prefs::kSaveFileDefaultDirectory, save_dir_.path());
296     BrowserThread::PostTask(
297         BrowserThread::IO, FROM_HERE,
298         base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
299   }
300 
NavigateToMockURL(const std::string & prefix)301   GURL NavigateToMockURL(const std::string& prefix) {
302     GURL url = URLRequestMockHTTPJob::GetMockUrl(
303         base::FilePath(kTestDir).AppendASCII(prefix + ".htm"));
304     ui_test_utils::NavigateToURL(browser(), url);
305     return url;
306   }
307 
308   // Returns full paths of destination file and directory.
GetDestinationPaths(const std::string & prefix,base::FilePath * full_file_name,base::FilePath * dir)309   void GetDestinationPaths(const std::string& prefix,
310                 base::FilePath* full_file_name,
311                 base::FilePath* dir) {
312     *full_file_name = save_dir_.path().AppendASCII(prefix + ".htm");
313     *dir = save_dir_.path().AppendASCII(prefix + "_files");
314   }
315 
GetCurrentTab(Browser * browser) const316   WebContents* GetCurrentTab(Browser* browser) const {
317     WebContents* current_tab =
318         browser->tab_strip_model()->GetActiveWebContents();
319     EXPECT_TRUE(current_tab);
320     return current_tab;
321   }
322 
323   // Returns true if and when there was a single download created, and its url
324   // is |expected_url|.
VerifySavePackageExpectations(Browser * browser,const GURL & expected_url) const325   bool VerifySavePackageExpectations(
326       Browser* browser,
327       const GURL& expected_url) const {
328     // Generally, there should only be one download item created
329     // in all of these tests.  If it's already here, grab it; if not,
330     // wait for it to show up.
331     std::vector<DownloadItem*> items;
332     DownloadManager* manager(
333         BrowserContext::GetDownloadManager(browser->profile()));
334     manager->GetAllDownloads(&items);
335     if (items.size() == 0u) {
336       DownloadItemCreatedObserver(manager).WaitForDownloadItem(&items);
337     }
338 
339     EXPECT_EQ(1u, items.size());
340     if (1u != items.size())
341       return false;
342     DownloadItem* download_item(items[0]);
343 
344     return (expected_url == download_item->GetOriginalUrl());
345   }
346 
347   // Note on synchronization:
348   //
349   // For each Save Page As operation, we create a corresponding shell
350   // DownloadItem to display progress to the user.  That DownloadItem goes
351   // through its own state transitions, including being persisted out to the
352   // history database, and the download shelf is not shown until after the
353   // persistence occurs.  Save Package completion (and marking the DownloadItem
354   // as completed) occurs asynchronously from persistence.  Thus if we want to
355   // examine either UI state or DB state, we need to wait until both the save
356   // package operation is complete and the relevant download item has been
357   // persisted.
358 
GetDownloadManager() const359   DownloadManager* GetDownloadManager() const {
360     DownloadManager* download_manager =
361         BrowserContext::GetDownloadManager(browser()->profile());
362     EXPECT_TRUE(download_manager);
363     return download_manager;
364   }
365 
366   // Path to directory containing test data.
367   base::FilePath test_dir_;
368 
369   // Temporary directory we will save pages to.
370   base::ScopedTempDir save_dir_;
371 
372  private:
373   DISALLOW_COPY_AND_ASSIGN(SavePageBrowserTest);
374 };
375 
~SavePageBrowserTest()376 SavePageBrowserTest::~SavePageBrowserTest() {
377 }
378 
379 // Disabled on Windows due to flakiness. http://crbug.com/162323
380 #if defined(OS_WIN)
381 #define MAYBE_SaveHTMLOnly DISABLED_SaveHTMLOnly
382 #else
383 #define MAYBE_SaveHTMLOnly SaveHTMLOnly
384 #endif
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,MAYBE_SaveHTMLOnly)385 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveHTMLOnly) {
386   GURL url = NavigateToMockURL("a");
387 
388   base::FilePath full_file_name, dir;
389   GetDestinationPaths("a", &full_file_name, &dir);
390   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
391       &DownloadStoredProperly, url, full_file_name, 1,
392       DownloadItem::COMPLETE));
393   scoped_refptr<content::MessageLoopRunner> loop_runner(
394       new content::MessageLoopRunner);
395   SavePackageFinishedObserver observer(
396       content::BrowserContext::GetDownloadManager(browser()->profile()),
397       loop_runner->QuitClosure());
398   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
399                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
400   loop_runner->Run();
401   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
402   persisted.WaitForPersisted();
403   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
404   EXPECT_TRUE(base::PathExists(full_file_name));
405   EXPECT_FALSE(base::PathExists(dir));
406   EXPECT_TRUE(base::ContentsEqual(test_dir_.Append(base::FilePath(
407       kTestDir)).Append(FILE_PATH_LITERAL("a.htm")), full_file_name));
408 }
409 
410 // http://crbug.com/162323
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,DISABLED_SaveHTMLOnlyCancel)411 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, DISABLED_SaveHTMLOnlyCancel) {
412   GURL url = NavigateToMockURL("a");
413   DownloadManager* manager(GetDownloadManager());
414   std::vector<DownloadItem*> downloads;
415   manager->GetAllDownloads(&downloads);
416   ASSERT_EQ(0u, downloads.size());
417 
418   base::FilePath full_file_name, dir;
419   GetDestinationPaths("a", &full_file_name, &dir);
420   DownloadItemCreatedObserver creation_observer(manager);
421   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
422       &DownloadStoredProperly, url, full_file_name, -1,
423       DownloadItem::CANCELLED));
424   // -1 to disable number of files check; we don't update after cancel, and
425   // we don't know when the single file completed in relationship to
426   // the cancel.
427 
428   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
429                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
430   std::vector<DownloadItem*> items;
431   creation_observer.WaitForDownloadItem(&items);
432   ASSERT_EQ(1UL, items.size());
433   ASSERT_EQ(url.spec(), items[0]->GetOriginalUrl().spec());
434   items[0]->Cancel(true);
435   // TODO(rdsmith): Fix DII::Cancel() to actually cancel the save package.
436   // Currently it's ignored.
437 
438   persisted.WaitForPersisted();
439 
440   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
441 
442   // TODO(benjhayden): Figure out how to safely wait for SavePackage's finished
443   // notification, then expect the contents of the downloaded file.
444 }
445 
446 class DelayingDownloadManagerDelegate : public ChromeDownloadManagerDelegate {
447  public:
DelayingDownloadManagerDelegate(Profile * profile)448   explicit DelayingDownloadManagerDelegate(Profile* profile)
449     : ChromeDownloadManagerDelegate(profile) {
450   }
~DelayingDownloadManagerDelegate()451   virtual ~DelayingDownloadManagerDelegate() {}
452 
ShouldCompleteDownload(content::DownloadItem * item,const base::Closure & user_complete_callback)453   virtual bool ShouldCompleteDownload(
454       content::DownloadItem* item,
455       const base::Closure& user_complete_callback) OVERRIDE {
456     return false;
457   }
458 
459  private:
460   DISALLOW_COPY_AND_ASSIGN(DelayingDownloadManagerDelegate);
461 };
462 
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,SaveHTMLOnlyTabDestroy)463 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveHTMLOnlyTabDestroy) {
464   GURL url = NavigateToMockURL("a");
465   scoped_ptr<DelayingDownloadManagerDelegate> delaying_delegate(
466       new DelayingDownloadManagerDelegate(browser()->profile()));
467   delaying_delegate->GetDownloadIdReceiverCallback().Run(
468       content::DownloadItem::kInvalidId + 1);
469   DownloadServiceFactory::GetForBrowserContext(browser()->profile())->
470       SetDownloadManagerDelegateForTesting(
471           delaying_delegate.PassAs<ChromeDownloadManagerDelegate>());
472   DownloadManager* manager(GetDownloadManager());
473   std::vector<DownloadItem*> downloads;
474   manager->GetAllDownloads(&downloads);
475   ASSERT_EQ(0u, downloads.size());
476 
477   base::FilePath full_file_name, dir;
478   GetDestinationPaths("a", &full_file_name, &dir);
479   DownloadItemCreatedObserver creation_observer(manager);
480   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
481                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
482   std::vector<DownloadItem*> items;
483   creation_observer.WaitForDownloadItem(&items);
484   ASSERT_TRUE(items.size() == 1);
485 
486   // Close the tab; does this cancel the download?
487   GetCurrentTab(browser())->Close();
488   EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
489 
490   EXPECT_FALSE(base::PathExists(full_file_name));
491   EXPECT_FALSE(base::PathExists(dir));
492 }
493 
494 // Disabled on Windows due to flakiness. http://crbug.com/162323
495 #if defined(OS_WIN)
496 #define MAYBE_SaveViewSourceHTMLOnly DISABLED_SaveViewSourceHTMLOnly
497 #else
498 #define MAYBE_SaveViewSourceHTMLOnly SaveViewSourceHTMLOnly
499 #endif
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,MAYBE_SaveViewSourceHTMLOnly)500 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveViewSourceHTMLOnly) {
501   base::FilePath file_name(FILE_PATH_LITERAL("a.htm"));
502   GURL view_source_url = URLRequestMockHTTPJob::GetMockViewSourceUrl(
503       base::FilePath(kTestDir).Append(file_name));
504   GURL actual_page_url = URLRequestMockHTTPJob::GetMockUrl(
505       base::FilePath(kTestDir).Append(file_name));
506   ui_test_utils::NavigateToURL(browser(), view_source_url);
507 
508   base::FilePath full_file_name, dir;
509   GetDestinationPaths("a", &full_file_name, &dir);
510   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
511       &DownloadStoredProperly, actual_page_url, full_file_name, 1,
512       DownloadItem::COMPLETE));
513   scoped_refptr<content::MessageLoopRunner> loop_runner(
514       new content::MessageLoopRunner);
515   SavePackageFinishedObserver observer(
516       content::BrowserContext::GetDownloadManager(browser()->profile()),
517       loop_runner->QuitClosure());
518   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
519                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
520   loop_runner->Run();
521   ASSERT_TRUE(VerifySavePackageExpectations(browser(), actual_page_url));
522   persisted.WaitForPersisted();
523 
524   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
525 
526   EXPECT_TRUE(base::PathExists(full_file_name));
527   EXPECT_FALSE(base::PathExists(dir));
528   EXPECT_TRUE(base::ContentsEqual(
529       test_dir_.Append(base::FilePath(kTestDir)).Append(file_name),
530       full_file_name));
531 }
532 
533 // Disabled on Windows due to flakiness. http://crbug.com/162323
534 #if defined(OS_WIN)
535 #define MAYBE_SaveCompleteHTML DISABLED_SaveCompleteHTML
536 #else
537 #define MAYBE_SaveCompleteHTML SaveCompleteHTML
538 #endif
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,MAYBE_SaveCompleteHTML)539 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveCompleteHTML) {
540   GURL url = NavigateToMockURL("b");
541 
542   base::FilePath full_file_name, dir;
543   GetDestinationPaths("b", &full_file_name, &dir);
544   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
545       &DownloadStoredProperly, url, full_file_name, 3,
546       DownloadItem::COMPLETE));
547   scoped_refptr<content::MessageLoopRunner> loop_runner(
548       new content::MessageLoopRunner);
549   SavePackageFinishedObserver observer(
550       content::BrowserContext::GetDownloadManager(browser()->profile()),
551       loop_runner->QuitClosure());
552   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(
553       full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
554   loop_runner->Run();
555   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
556   persisted.WaitForPersisted();
557 
558   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
559 
560   EXPECT_TRUE(base::PathExists(full_file_name));
561   EXPECT_TRUE(base::PathExists(dir));
562   EXPECT_TRUE(base::TextContentsEqual(
563       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("b.saved1.htm"),
564       full_file_name));
565   EXPECT_TRUE(base::ContentsEqual(
566       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.png"),
567       dir.AppendASCII("1.png")));
568   EXPECT_TRUE(base::ContentsEqual(
569       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.css"),
570       dir.AppendASCII("1.css")));
571 }
572 
573 // Invoke a save page during the initial navigation.
574 // (Regression test for http://crbug.com/156538).
575 // Disabled on Windows due to flakiness. http://crbug.com/162323
576 #if defined(OS_WIN)
577 #define MAYBE_SaveDuringInitialNavigationIncognito DISABLED_SaveDuringInitialNavigationIncognito
578 #else
579 #define MAYBE_SaveDuringInitialNavigationIncognito SaveDuringInitialNavigationIncognito
580 #endif
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,MAYBE_SaveDuringInitialNavigationIncognito)581 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,
582                        MAYBE_SaveDuringInitialNavigationIncognito) {
583   // Open an Incognito window.
584   Browser* incognito = CreateIncognitoBrowser();  // Waits.
585   ASSERT_TRUE(incognito);
586 
587   // Create a download item creation waiter on that window.
588   DownloadItemCreatedObserver creation_observer(
589       BrowserContext::GetDownloadManager(incognito->profile()));
590 
591   // Navigate, unblocking with new tab.
592   GURL url = URLRequestMockHTTPJob::GetMockUrl(
593       base::FilePath(kTestDir).AppendASCII("b.htm"));
594   NavigateToURLWithDisposition(incognito, url, NEW_FOREGROUND_TAB,
595                                ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
596 
597   // Save the page before completion.
598   base::FilePath full_file_name, dir;
599   GetDestinationPaths("b", &full_file_name, &dir);
600   scoped_refptr<content::MessageLoopRunner> loop_runner(
601       new content::MessageLoopRunner);
602   SavePackageFinishedObserver observer(
603       content::BrowserContext::GetDownloadManager(incognito->profile()),
604       loop_runner->QuitClosure());
605   ASSERT_TRUE(GetCurrentTab(incognito)->SavePage(
606       full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
607 
608   loop_runner->Run();
609   ASSERT_TRUE(VerifySavePackageExpectations(incognito, url));
610 
611   // Confirm download shelf is visible.
612   EXPECT_TRUE(incognito->window()->IsDownloadShelfVisible());
613 
614   // We can't check more than this because SavePackage is racing with
615   // the page load.  If the page load won the race, then SavePackage
616   // might have completed. If the page load lost the race, then
617   // SavePackage will cancel because there aren't any resources to
618   // save.
619 }
620 
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,NoSave)621 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, NoSave) {
622   ui_test_utils::NavigateToURL(browser(), GURL(content::kAboutBlankURL));
623   EXPECT_FALSE(chrome::CanSavePage(browser()));
624 }
625 
626 // Disabled on Windows due to flakiness. http://crbug.com/162323
627 #if defined(OS_WIN)
628 #define MAYBE_FileNameFromPageTitle DISABLED_FileNameFromPageTitle
629 #else
630 #define MAYBE_FileNameFromPageTitle FileNameFromPageTitle
631 #endif
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,MAYBE_FileNameFromPageTitle)632 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_FileNameFromPageTitle) {
633   GURL url = NavigateToMockURL("b");
634 
635   base::FilePath full_file_name = save_dir_.path().AppendASCII(
636       std::string("Test page for saving page feature") + kAppendedExtension);
637   base::FilePath dir = save_dir_.path().AppendASCII(
638       "Test page for saving page feature_files");
639   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
640       &DownloadStoredProperly, url, full_file_name, 3,
641       DownloadItem::COMPLETE));
642   scoped_refptr<content::MessageLoopRunner> loop_runner(
643       new content::MessageLoopRunner);
644   SavePackageFinishedObserver observer(
645       content::BrowserContext::GetDownloadManager(browser()->profile()),
646       loop_runner->QuitClosure());
647   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(
648       full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
649 
650   loop_runner->Run();
651   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
652   persisted.WaitForPersisted();
653 
654   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
655 
656   EXPECT_TRUE(base::PathExists(full_file_name));
657   EXPECT_TRUE(base::PathExists(dir));
658   EXPECT_TRUE(base::TextContentsEqual(
659       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("b.saved2.htm"),
660       full_file_name));
661   EXPECT_TRUE(base::ContentsEqual(
662       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.png"),
663       dir.AppendASCII("1.png")));
664   EXPECT_TRUE(base::ContentsEqual(
665       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.css"),
666       dir.AppendASCII("1.css")));
667 }
668 
669 // Disabled on Windows due to flakiness. http://crbug.com/162323
670 #if defined(OS_WIN)
671 #define MAYBE_RemoveFromList DISABLED_RemoveFromList
672 #else
673 #define MAYBE_RemoveFromList RemoveFromList
674 #endif
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,MAYBE_RemoveFromList)675 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_RemoveFromList) {
676   GURL url = NavigateToMockURL("a");
677 
678   base::FilePath full_file_name, dir;
679   GetDestinationPaths("a", &full_file_name, &dir);
680   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
681       &DownloadStoredProperly, url, full_file_name, 1,
682       DownloadItem::COMPLETE));
683   scoped_refptr<content::MessageLoopRunner> loop_runner(
684       new content::MessageLoopRunner);
685   SavePackageFinishedObserver observer(
686       content::BrowserContext::GetDownloadManager(browser()->profile()),
687       loop_runner->QuitClosure());
688   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
689                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
690 
691   loop_runner->Run();
692   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
693   persisted.WaitForPersisted();
694 
695   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
696 
697   DownloadManager* manager(GetDownloadManager());
698   std::vector<DownloadItem*> downloads;
699   manager->GetAllDownloads(&downloads);
700   ASSERT_EQ(1UL, downloads.size());
701   DownloadRemovedObserver removed(browser()->profile(), downloads[0]->GetId());
702 
703   EXPECT_EQ(manager->RemoveAllDownloads(), 1);
704 
705   removed.WaitForRemoved();
706 
707   EXPECT_TRUE(base::PathExists(full_file_name));
708   EXPECT_FALSE(base::PathExists(dir));
709   EXPECT_TRUE(base::ContentsEqual(test_dir_.Append(base::FilePath(
710       kTestDir)).Append(FILE_PATH_LITERAL("a.htm")), full_file_name));
711 }
712 
713 // This tests that a webpage with the title "test.exe" is saved as
714 // "test.exe.htm".
715 // We probably don't care to handle this on Linux or Mac.
716 #if defined(OS_WIN)
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,CleanFilenameFromPageTitle)717 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, CleanFilenameFromPageTitle) {
718   const base::FilePath file_name(FILE_PATH_LITERAL("c.htm"));
719   base::FilePath download_dir =
720       DownloadPrefs::FromDownloadManager(GetDownloadManager())->
721           DownloadPath();
722   base::FilePath full_file_name =
723       download_dir.AppendASCII(std::string("test.exe") + kAppendedExtension);
724   base::FilePath dir = download_dir.AppendASCII("test.exe_files");
725 
726   EXPECT_FALSE(base::PathExists(full_file_name));
727   GURL url = URLRequestMockHTTPJob::GetMockUrl(
728       base::FilePath(kTestDir).Append(file_name));
729   ui_test_utils::NavigateToURL(browser(), url);
730 
731   SavePackageFilePicker::SetShouldPromptUser(false);
732   scoped_refptr<content::MessageLoopRunner> loop_runner(
733       new content::MessageLoopRunner);
734   SavePackageFinishedObserver observer(
735       content::BrowserContext::GetDownloadManager(browser()->profile()),
736       loop_runner->QuitClosure());
737   chrome::SavePage(browser());
738   loop_runner->Run();
739 
740   EXPECT_TRUE(base::PathExists(full_file_name));
741 
742   EXPECT_TRUE(file_util::DieFileDie(full_file_name, false));
743   EXPECT_TRUE(file_util::DieFileDie(dir, true));
744 }
745 #endif
746 
747 class SavePageAsMHTMLBrowserTest : public SavePageBrowserTest {
748  public:
SavePageAsMHTMLBrowserTest()749   SavePageAsMHTMLBrowserTest() {}
750   virtual ~SavePageAsMHTMLBrowserTest();
SetUpCommandLine(CommandLine * command_line)751   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
752     command_line->AppendSwitch(switches::kSavePageAsMHTML);
753   }
754 
755  private:
756   DISALLOW_COPY_AND_ASSIGN(SavePageAsMHTMLBrowserTest);
757 };
758 
~SavePageAsMHTMLBrowserTest()759 SavePageAsMHTMLBrowserTest::~SavePageAsMHTMLBrowserTest() {
760 }
761 
IN_PROC_BROWSER_TEST_F(SavePageAsMHTMLBrowserTest,SavePageAsMHTML)762 IN_PROC_BROWSER_TEST_F(SavePageAsMHTMLBrowserTest, SavePageAsMHTML) {
763   static const int64 kFileSizeMin = 2758;
764   GURL url = NavigateToMockURL("b");
765   base::FilePath download_dir = DownloadPrefs::FromDownloadManager(
766       GetDownloadManager())->DownloadPath();
767   base::FilePath full_file_name = download_dir.AppendASCII(std::string(
768       "Test page for saving page feature.mhtml"));
769   SavePackageFilePicker::SetShouldPromptUser(false);
770   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
771       &DownloadStoredProperly, url, full_file_name, -1,
772       DownloadItem::COMPLETE));
773   scoped_refptr<content::MessageLoopRunner> loop_runner(
774       new content::MessageLoopRunner);
775   SavePackageFinishedObserver observer(
776       content::BrowserContext::GetDownloadManager(browser()->profile()),
777       loop_runner->QuitClosure());
778   chrome::SavePage(browser());
779   loop_runner->Run();
780   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
781   persisted.WaitForPersisted();
782 
783   ASSERT_TRUE(base::PathExists(full_file_name));
784   int64 actual_file_size = -1;
785   EXPECT_TRUE(base::GetFileSize(full_file_name, &actual_file_size));
786   EXPECT_LE(kFileSizeMin, actual_file_size);
787 }
788 
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,SavePageBrowserTest_NonMHTML)789 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SavePageBrowserTest_NonMHTML) {
790   SavePackageFilePicker::SetShouldPromptUser(false);
791   GURL url("data:text/plain,foo");
792   ui_test_utils::NavigateToURL(browser(), url);
793   scoped_refptr<content::MessageLoopRunner> loop_runner(
794       new content::MessageLoopRunner);
795   SavePackageFinishedObserver observer(
796       content::BrowserContext::GetDownloadManager(browser()->profile()),
797       loop_runner->QuitClosure());
798   chrome::SavePage(browser());
799   loop_runner->Run();
800   base::FilePath download_dir = DownloadPrefs::FromDownloadManager(
801       GetDownloadManager())->DownloadPath();
802   base::FilePath filename = download_dir.AppendASCII("dataurl.txt");
803   ASSERT_TRUE(base::PathExists(filename));
804   std::string contents;
805   EXPECT_TRUE(base::ReadFileToString(filename, &contents));
806   EXPECT_EQ("foo", contents);
807 }
808 
809 }  // namespace
810 
811