Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / download / save_page_browsertest.cc
blobb18908031b536ddfdb6d208bb947b1896f5b63f2
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.
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.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/common/url_constants.h"
41 #include "content/public/test/test_utils.h"
42 #include "net/test/url_request/url_request_mock_http_job.h"
43 #include "testing/gtest/include/gtest/gtest.h"
45 using content::BrowserContext;
46 using content::BrowserThread;
47 using content::DownloadItem;
48 using content::DownloadManager;
49 using content::WebContents;
50 using net::URLRequestMockHTTPJob;
52 namespace {
54 // Waits for an item record in the downloads database to match |filter|. See
55 // DownloadStoredProperly() below for an example filter.
56 class DownloadPersistedObserver : public DownloadHistory::Observer {
57 public:
58 typedef base::Callback<bool(
59 DownloadItem* item,
60 const history::DownloadRow&)> PersistedFilter;
62 DownloadPersistedObserver(Profile* profile, const PersistedFilter& filter)
63 : profile_(profile),
64 filter_(filter),
65 waiting_(false),
66 persisted_(false) {
67 DownloadServiceFactory::GetForBrowserContext(profile_)->
68 GetDownloadHistory()->AddObserver(this);
71 virtual ~DownloadPersistedObserver() {
72 DownloadService* service = DownloadServiceFactory::GetForBrowserContext(
73 profile_);
74 if (service && service->GetDownloadHistory())
75 service->GetDownloadHistory()->RemoveObserver(this);
78 bool WaitForPersisted() {
79 if (persisted_)
80 return true;
81 waiting_ = true;
82 content::RunMessageLoop();
83 waiting_ = false;
84 return persisted_;
87 virtual void OnDownloadStored(DownloadItem* item,
88 const history::DownloadRow& info) override {
89 persisted_ = persisted_ || filter_.Run(item, info);
90 if (persisted_ && waiting_)
91 base::MessageLoopForUI::current()->Quit();
94 private:
95 Profile* profile_;
96 PersistedFilter filter_;
97 bool waiting_;
98 bool persisted_;
100 DISALLOW_COPY_AND_ASSIGN(DownloadPersistedObserver);
103 // Waits for an item record to be removed from the downloads database.
104 class DownloadRemovedObserver : public DownloadPersistedObserver {
105 public:
106 DownloadRemovedObserver(Profile* profile, int32 download_id)
107 : DownloadPersistedObserver(profile, PersistedFilter()),
108 removed_(false),
109 waiting_(false),
110 download_id_(download_id) {
112 virtual ~DownloadRemovedObserver() {}
114 bool WaitForRemoved() {
115 if (removed_)
116 return true;
117 waiting_ = true;
118 content::RunMessageLoop();
119 waiting_ = false;
120 return removed_;
123 virtual void OnDownloadStored(DownloadItem* item,
124 const history::DownloadRow& info) override {
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();
133 private:
134 bool removed_;
135 bool waiting_;
136 int32 download_id_;
138 DISALLOW_COPY_AND_ASSIGN(DownloadRemovedObserver);
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;
156 if (info.url_chain.size() != 1u) {
157 VLOG(20) << __FUNCTION__ << " " << info.url_chain.size()
158 << " != 1";
159 return false;
161 if (info.url_chain[0] != expected_url) {
162 VLOG(20) << __FUNCTION__ << " " << info.url_chain[0].spec()
163 << " != " << expected_url.spec();
164 return false;
166 if ((num_files >= 0) && (info.received_bytes != num_files)) {
167 VLOG(20) << __FUNCTION__ << " " << num_files
168 << " != " << info.received_bytes;
169 return false;
171 if (info.state != expected_state) {
172 VLOG(20) << __FUNCTION__ << " " << info.state
173 << " != " << expected_state;
174 return false;
176 return true;
179 const base::FilePath::CharType kTestDir[] = FILE_PATH_LITERAL("save_page");
181 static const char kAppendedExtension[] = ".html";
183 // Loosely based on logic in DownloadTestObserver.
184 class DownloadItemCreatedObserver : public DownloadManager::Observer {
185 public:
186 explicit DownloadItemCreatedObserver(DownloadManager* manager)
187 : waiting_(false), manager_(manager) {
188 manager->AddObserver(this);
191 virtual ~DownloadItemCreatedObserver() {
192 if (manager_)
193 manager_->RemoveObserver(this);
196 // Wait for the first download item created after object creation.
197 // Note that this class provides no protection against the download
198 // being destroyed between creation and return of WaitForNewDownloadItem();
199 // the caller must guarantee that in some other fashion.
200 void WaitForDownloadItem(std::vector<DownloadItem*>* items_seen) {
201 if (!manager_) {
202 // The manager went away before we were asked to wait; return
203 // what we have, even if it's null.
204 *items_seen = items_seen_;
205 return;
208 if (items_seen_.empty()) {
209 waiting_ = true;
210 content::RunMessageLoop();
211 waiting_ = false;
214 *items_seen = items_seen_;
215 return;
218 private:
219 // DownloadManager::Observer
220 virtual void OnDownloadCreated(
221 DownloadManager* manager, DownloadItem* item) override {
222 DCHECK_EQ(manager, manager_);
223 items_seen_.push_back(item);
225 if (waiting_)
226 base::MessageLoopForUI::current()->Quit();
229 virtual void ManagerGoingDown(DownloadManager* manager) override {
230 manager_->RemoveObserver(this);
231 manager_ = NULL;
232 if (waiting_)
233 base::MessageLoopForUI::current()->Quit();
236 bool waiting_;
237 DownloadManager* manager_;
238 std::vector<DownloadItem*> items_seen_;
240 DISALLOW_COPY_AND_ASSIGN(DownloadItemCreatedObserver);
243 class SavePackageFinishedObserver : public content::DownloadManager::Observer {
244 public:
245 SavePackageFinishedObserver(content::DownloadManager* manager,
246 const base::Closure& callback)
247 : download_manager_(manager),
248 callback_(callback) {
249 download_manager_->AddObserver(this);
252 virtual ~SavePackageFinishedObserver() {
253 if (download_manager_)
254 download_manager_->RemoveObserver(this);
257 // DownloadManager::Observer:
258 virtual void OnSavePackageSuccessfullyFinished(
259 content::DownloadManager* manager, content::DownloadItem* item) override {
260 callback_.Run();
262 virtual void ManagerGoingDown(content::DownloadManager* manager) override {
263 download_manager_->RemoveObserver(this);
264 download_manager_ = NULL;
267 private:
268 content::DownloadManager* download_manager_;
269 base::Closure callback_;
271 DISALLOW_COPY_AND_ASSIGN(SavePackageFinishedObserver);
274 class SavePageBrowserTest : public InProcessBrowserTest {
275 public:
276 SavePageBrowserTest() {}
277 virtual ~SavePageBrowserTest();
279 protected:
280 virtual void SetUp() override {
281 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir_));
282 ASSERT_TRUE(save_dir_.CreateUniqueTempDir());
283 InProcessBrowserTest::SetUp();
286 virtual void SetUpOnMainThread() override {
287 browser()->profile()->GetPrefs()->SetFilePath(
288 prefs::kDownloadDefaultDirectory, save_dir_.path());
289 browser()->profile()->GetPrefs()->SetFilePath(
290 prefs::kSaveFileDefaultDirectory, save_dir_.path());
291 BrowserThread::PostTask(
292 BrowserThread::IO, FROM_HERE,
293 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
296 GURL NavigateToMockURL(const std::string& prefix) {
297 GURL url = URLRequestMockHTTPJob::GetMockUrl(
298 base::FilePath(kTestDir).AppendASCII(prefix + ".htm"));
299 ui_test_utils::NavigateToURL(browser(), url);
300 return url;
303 // Returns full paths of destination file and directory.
304 void GetDestinationPaths(const std::string& prefix,
305 base::FilePath* full_file_name,
306 base::FilePath* dir) {
307 *full_file_name = save_dir_.path().AppendASCII(prefix + ".htm");
308 *dir = save_dir_.path().AppendASCII(prefix + "_files");
311 WebContents* GetCurrentTab(Browser* browser) const {
312 WebContents* current_tab =
313 browser->tab_strip_model()->GetActiveWebContents();
314 EXPECT_TRUE(current_tab);
315 return current_tab;
318 // Returns true if and when there was a single download created, and its url
319 // is |expected_url|.
320 bool VerifySavePackageExpectations(
321 Browser* browser,
322 const GURL& expected_url) const {
323 // Generally, there should only be one download item created
324 // in all of these tests. If it's already here, grab it; if not,
325 // wait for it to show up.
326 std::vector<DownloadItem*> items;
327 DownloadManager* manager(
328 BrowserContext::GetDownloadManager(browser->profile()));
329 manager->GetAllDownloads(&items);
330 if (items.size() == 0u) {
331 DownloadItemCreatedObserver(manager).WaitForDownloadItem(&items);
334 EXPECT_EQ(1u, items.size());
335 if (1u != items.size())
336 return false;
337 DownloadItem* download_item(items[0]);
339 return (expected_url == download_item->GetOriginalUrl());
342 // Note on synchronization:
344 // For each Save Page As operation, we create a corresponding shell
345 // DownloadItem to display progress to the user. That DownloadItem goes
346 // through its own state transitions, including being persisted out to the
347 // history database, and the download shelf is not shown until after the
348 // persistence occurs. Save Package completion (and marking the DownloadItem
349 // as completed) occurs asynchronously from persistence. Thus if we want to
350 // examine either UI state or DB state, we need to wait until both the save
351 // package operation is complete and the relevant download item has been
352 // persisted.
354 DownloadManager* GetDownloadManager() const {
355 DownloadManager* download_manager =
356 BrowserContext::GetDownloadManager(browser()->profile());
357 EXPECT_TRUE(download_manager);
358 return download_manager;
361 // Path to directory containing test data.
362 base::FilePath test_dir_;
364 // Temporary directory we will save pages to.
365 base::ScopedTempDir save_dir_;
367 private:
368 DISALLOW_COPY_AND_ASSIGN(SavePageBrowserTest);
371 SavePageBrowserTest::~SavePageBrowserTest() {
374 // Disabled on Windows due to flakiness. http://crbug.com/162323
375 #if defined(OS_WIN)
376 #define MAYBE_SaveHTMLOnly DISABLED_SaveHTMLOnly
377 #else
378 #define MAYBE_SaveHTMLOnly SaveHTMLOnly
379 #endif
380 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveHTMLOnly) {
381 GURL url = NavigateToMockURL("a");
383 base::FilePath full_file_name, dir;
384 GetDestinationPaths("a", &full_file_name, &dir);
385 DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
386 &DownloadStoredProperly, url, full_file_name, 1,
387 DownloadItem::COMPLETE));
388 scoped_refptr<content::MessageLoopRunner> loop_runner(
389 new content::MessageLoopRunner);
390 SavePackageFinishedObserver observer(
391 content::BrowserContext::GetDownloadManager(browser()->profile()),
392 loop_runner->QuitClosure());
393 ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
394 content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
395 loop_runner->Run();
396 ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
397 persisted.WaitForPersisted();
398 EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
399 EXPECT_TRUE(base::PathExists(full_file_name));
400 EXPECT_FALSE(base::PathExists(dir));
401 EXPECT_TRUE(base::ContentsEqual(test_dir_.Append(base::FilePath(
402 kTestDir)).Append(FILE_PATH_LITERAL("a.htm")), full_file_name));
405 // http://crbug.com/162323
406 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, DISABLED_SaveHTMLOnlyCancel) {
407 GURL url = NavigateToMockURL("a");
408 DownloadManager* manager(GetDownloadManager());
409 std::vector<DownloadItem*> downloads;
410 manager->GetAllDownloads(&downloads);
411 ASSERT_EQ(0u, downloads.size());
413 base::FilePath full_file_name, dir;
414 GetDestinationPaths("a", &full_file_name, &dir);
415 DownloadItemCreatedObserver creation_observer(manager);
416 DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
417 &DownloadStoredProperly, url, full_file_name, -1,
418 DownloadItem::CANCELLED));
419 // -1 to disable number of files check; we don't update after cancel, and
420 // we don't know when the single file completed in relationship to
421 // the cancel.
423 ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
424 content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
425 std::vector<DownloadItem*> items;
426 creation_observer.WaitForDownloadItem(&items);
427 ASSERT_EQ(1UL, items.size());
428 ASSERT_EQ(url.spec(), items[0]->GetOriginalUrl().spec());
429 items[0]->Cancel(true);
430 // TODO(rdsmith): Fix DII::Cancel() to actually cancel the save package.
431 // Currently it's ignored.
433 persisted.WaitForPersisted();
435 EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
437 // TODO(benjhayden): Figure out how to safely wait for SavePackage's finished
438 // notification, then expect the contents of the downloaded file.
441 class DelayingDownloadManagerDelegate : public ChromeDownloadManagerDelegate {
442 public:
443 explicit DelayingDownloadManagerDelegate(Profile* profile)
444 : ChromeDownloadManagerDelegate(profile) {
446 virtual ~DelayingDownloadManagerDelegate() {}
448 virtual bool ShouldCompleteDownload(
449 content::DownloadItem* item,
450 const base::Closure& user_complete_callback) override {
451 return false;
454 private:
455 DISALLOW_COPY_AND_ASSIGN(DelayingDownloadManagerDelegate);
458 // Disabled on Windows due to flakiness. http://crbug.com/162323
459 #if defined(OS_WIN)
460 #define MAYBE_SaveHTMLOnlyTabDestroy DISABLED_SaveHTMLOnlyTabDestroy
461 #else
462 #define MAYBE_SaveHTMLOnlyTabDestroy SaveHTMLOnlyTabDestroy
463 #endif
464 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveHTMLOnlyTabDestroy) {
465 GURL url = NavigateToMockURL("a");
466 scoped_ptr<DelayingDownloadManagerDelegate> delaying_delegate(
467 new DelayingDownloadManagerDelegate(browser()->profile()));
468 delaying_delegate->GetDownloadIdReceiverCallback().Run(
469 content::DownloadItem::kInvalidId + 1);
470 DownloadServiceFactory::GetForBrowserContext(browser()->profile())
471 ->SetDownloadManagerDelegateForTesting(delaying_delegate.Pass());
472 DownloadManager* manager(GetDownloadManager());
473 std::vector<DownloadItem*> downloads;
474 manager->GetAllDownloads(&downloads);
475 ASSERT_EQ(0u, downloads.size());
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);
486 // Close the tab; does this cancel the download?
487 GetCurrentTab(browser())->Close();
488 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
490 EXPECT_FALSE(base::PathExists(full_file_name));
491 EXPECT_FALSE(base::PathExists(dir));
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
500 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveViewSourceHTMLOnly) {
501 base::FilePath file_name(FILE_PATH_LITERAL("a.htm"));
502 GURL mock_url = URLRequestMockHTTPJob::GetMockUrl(
503 base::FilePath(kTestDir).Append(file_name));
504 GURL view_source_url =
505 GURL(content::kViewSourceScheme + std::string(":") + mock_url.spec());
506 GURL actual_page_url = URLRequestMockHTTPJob::GetMockUrl(
507 base::FilePath(kTestDir).Append(file_name));
508 ui_test_utils::NavigateToURL(browser(), view_source_url);
510 base::FilePath full_file_name, dir;
511 GetDestinationPaths("a", &full_file_name, &dir);
512 DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
513 &DownloadStoredProperly, actual_page_url, full_file_name, 1,
514 DownloadItem::COMPLETE));
515 scoped_refptr<content::MessageLoopRunner> loop_runner(
516 new content::MessageLoopRunner);
517 SavePackageFinishedObserver observer(
518 content::BrowserContext::GetDownloadManager(browser()->profile()),
519 loop_runner->QuitClosure());
520 ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
521 content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
522 loop_runner->Run();
523 ASSERT_TRUE(VerifySavePackageExpectations(browser(), actual_page_url));
524 persisted.WaitForPersisted();
526 EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
528 EXPECT_TRUE(base::PathExists(full_file_name));
529 EXPECT_FALSE(base::PathExists(dir));
530 EXPECT_TRUE(base::ContentsEqual(
531 test_dir_.Append(base::FilePath(kTestDir)).Append(file_name),
532 full_file_name));
535 // Disabled on Windows due to flakiness. http://crbug.com/162323
536 #if defined(OS_WIN)
537 #define MAYBE_SaveCompleteHTML DISABLED_SaveCompleteHTML
538 #else
539 #define MAYBE_SaveCompleteHTML SaveCompleteHTML
540 #endif
541 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveCompleteHTML) {
542 GURL url = NavigateToMockURL("b");
544 base::FilePath full_file_name, dir;
545 GetDestinationPaths("b", &full_file_name, &dir);
546 DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
547 &DownloadStoredProperly, url, full_file_name, 3,
548 DownloadItem::COMPLETE));
549 scoped_refptr<content::MessageLoopRunner> loop_runner(
550 new content::MessageLoopRunner);
551 SavePackageFinishedObserver observer(
552 content::BrowserContext::GetDownloadManager(browser()->profile()),
553 loop_runner->QuitClosure());
554 ASSERT_TRUE(GetCurrentTab(browser())->SavePage(
555 full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
556 loop_runner->Run();
557 ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
558 persisted.WaitForPersisted();
560 EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
562 EXPECT_TRUE(base::PathExists(full_file_name));
563 EXPECT_TRUE(base::PathExists(dir));
564 #if 0
565 // Disabled until the following Blink CL is relanded and rolled:
566 // https://codereview.chromium.org/649413002
567 EXPECT_TRUE(base::TextContentsEqual(
568 test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("b.saved1.htm"),
569 full_file_name));
570 #endif
571 EXPECT_TRUE(base::ContentsEqual(
572 test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.png"),
573 dir.AppendASCII("1.png")));
574 EXPECT_TRUE(base::ContentsEqual(
575 test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.css"),
576 dir.AppendASCII("1.css")));
579 // Invoke a save page during the initial navigation.
580 // (Regression test for http://crbug.com/156538).
581 // Disabled on Windows due to flakiness. http://crbug.com/162323
582 #if defined(OS_WIN)
583 #define MAYBE_SaveDuringInitialNavigationIncognito DISABLED_SaveDuringInitialNavigationIncognito
584 #else
585 #define MAYBE_SaveDuringInitialNavigationIncognito SaveDuringInitialNavigationIncognito
586 #endif
587 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,
588 MAYBE_SaveDuringInitialNavigationIncognito) {
589 // Open an Incognito window.
590 Browser* incognito = CreateIncognitoBrowser(); // Waits.
591 ASSERT_TRUE(incognito);
593 // Create a download item creation waiter on that window.
594 DownloadItemCreatedObserver creation_observer(
595 BrowserContext::GetDownloadManager(incognito->profile()));
597 // Navigate, unblocking with new tab.
598 GURL url = URLRequestMockHTTPJob::GetMockUrl(
599 base::FilePath(kTestDir).AppendASCII("b.htm"));
600 NavigateToURLWithDisposition(incognito, url, NEW_FOREGROUND_TAB,
601 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
603 // Save the page before completion.
604 base::FilePath full_file_name, dir;
605 GetDestinationPaths("b", &full_file_name, &dir);
606 scoped_refptr<content::MessageLoopRunner> loop_runner(
607 new content::MessageLoopRunner);
608 SavePackageFinishedObserver observer(
609 content::BrowserContext::GetDownloadManager(incognito->profile()),
610 loop_runner->QuitClosure());
611 ASSERT_TRUE(GetCurrentTab(incognito)->SavePage(
612 full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
614 loop_runner->Run();
615 ASSERT_TRUE(VerifySavePackageExpectations(incognito, url));
617 // Confirm download shelf is visible.
618 EXPECT_TRUE(incognito->window()->IsDownloadShelfVisible());
620 // We can't check more than this because SavePackage is racing with
621 // the page load. If the page load won the race, then SavePackage
622 // might have completed. If the page load lost the race, then
623 // SavePackage will cancel because there aren't any resources to
624 // save.
627 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, NoSave) {
628 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
629 EXPECT_FALSE(chrome::CanSavePage(browser()));
632 // Disabled on Windows due to flakiness. http://crbug.com/162323
633 #if defined(OS_WIN)
634 #define MAYBE_FileNameFromPageTitle DISABLED_FileNameFromPageTitle
635 #else
636 #define MAYBE_FileNameFromPageTitle FileNameFromPageTitle
637 #endif
638 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_FileNameFromPageTitle) {
639 GURL url = NavigateToMockURL("b");
641 base::FilePath full_file_name = save_dir_.path().AppendASCII(
642 std::string("Test page for saving page feature") + kAppendedExtension);
643 base::FilePath dir = save_dir_.path().AppendASCII(
644 "Test page for saving page feature_files");
645 DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
646 &DownloadStoredProperly, url, full_file_name, 3,
647 DownloadItem::COMPLETE));
648 scoped_refptr<content::MessageLoopRunner> loop_runner(
649 new content::MessageLoopRunner);
650 SavePackageFinishedObserver observer(
651 content::BrowserContext::GetDownloadManager(browser()->profile()),
652 loop_runner->QuitClosure());
653 ASSERT_TRUE(GetCurrentTab(browser())->SavePage(
654 full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
656 loop_runner->Run();
657 ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
658 persisted.WaitForPersisted();
660 EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
662 EXPECT_TRUE(base::PathExists(full_file_name));
663 EXPECT_TRUE(base::PathExists(dir));
664 #if 0
665 // Disabled until the following Blink CL is relanded and rolled:
666 // https://codereview.chromium.org/649413002
667 EXPECT_TRUE(base::TextContentsEqual(
668 test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("b.saved2.htm"),
669 full_file_name));
670 #endif
671 EXPECT_TRUE(base::ContentsEqual(
672 test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.png"),
673 dir.AppendASCII("1.png")));
674 EXPECT_TRUE(base::ContentsEqual(
675 test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.css"),
676 dir.AppendASCII("1.css")));
679 // Disabled on Windows due to flakiness. http://crbug.com/162323
680 #if defined(OS_WIN)
681 #define MAYBE_RemoveFromList DISABLED_RemoveFromList
682 #else
683 #define MAYBE_RemoveFromList RemoveFromList
684 #endif
685 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_RemoveFromList) {
686 GURL url = NavigateToMockURL("a");
688 base::FilePath full_file_name, dir;
689 GetDestinationPaths("a", &full_file_name, &dir);
690 DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
691 &DownloadStoredProperly, url, full_file_name, 1,
692 DownloadItem::COMPLETE));
693 scoped_refptr<content::MessageLoopRunner> loop_runner(
694 new content::MessageLoopRunner);
695 SavePackageFinishedObserver observer(
696 content::BrowserContext::GetDownloadManager(browser()->profile()),
697 loop_runner->QuitClosure());
698 ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
699 content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
701 loop_runner->Run();
702 ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
703 persisted.WaitForPersisted();
705 EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
707 DownloadManager* manager(GetDownloadManager());
708 std::vector<DownloadItem*> downloads;
709 manager->GetAllDownloads(&downloads);
710 ASSERT_EQ(1UL, downloads.size());
711 DownloadRemovedObserver removed(browser()->profile(), downloads[0]->GetId());
713 EXPECT_EQ(manager->RemoveAllDownloads(), 1);
715 removed.WaitForRemoved();
717 EXPECT_TRUE(base::PathExists(full_file_name));
718 EXPECT_FALSE(base::PathExists(dir));
719 EXPECT_TRUE(base::ContentsEqual(test_dir_.Append(base::FilePath(
720 kTestDir)).Append(FILE_PATH_LITERAL("a.htm")), full_file_name));
723 // This tests that a webpage with the title "test.exe" is saved as
724 // "test.exe.htm".
725 // We probably don't care to handle this on Linux or Mac.
726 #if defined(OS_WIN)
727 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, CleanFilenameFromPageTitle) {
728 const base::FilePath file_name(FILE_PATH_LITERAL("c.htm"));
729 base::FilePath download_dir =
730 DownloadPrefs::FromDownloadManager(GetDownloadManager())->
731 DownloadPath();
732 base::FilePath full_file_name =
733 download_dir.AppendASCII(std::string("test.exe") + kAppendedExtension);
734 base::FilePath dir = download_dir.AppendASCII("test.exe_files");
736 EXPECT_FALSE(base::PathExists(full_file_name));
737 GURL url = URLRequestMockHTTPJob::GetMockUrl(
738 base::FilePath(kTestDir).Append(file_name));
739 ui_test_utils::NavigateToURL(browser(), url);
741 SavePackageFilePicker::SetShouldPromptUser(false);
742 scoped_refptr<content::MessageLoopRunner> loop_runner(
743 new content::MessageLoopRunner);
744 SavePackageFinishedObserver observer(
745 content::BrowserContext::GetDownloadManager(browser()->profile()),
746 loop_runner->QuitClosure());
747 chrome::SavePage(browser());
748 loop_runner->Run();
750 EXPECT_TRUE(base::PathExists(full_file_name));
752 EXPECT_TRUE(base::DieFileDie(full_file_name, false));
753 EXPECT_TRUE(base::DieFileDie(dir, true));
755 #endif
757 class SavePageAsMHTMLBrowserTest : public SavePageBrowserTest {
758 public:
759 SavePageAsMHTMLBrowserTest() {}
760 virtual ~SavePageAsMHTMLBrowserTest();
761 virtual void SetUpCommandLine(CommandLine* command_line) override {
762 command_line->AppendSwitch(switches::kSavePageAsMHTML);
765 private:
766 DISALLOW_COPY_AND_ASSIGN(SavePageAsMHTMLBrowserTest);
769 SavePageAsMHTMLBrowserTest::~SavePageAsMHTMLBrowserTest() {
772 IN_PROC_BROWSER_TEST_F(SavePageAsMHTMLBrowserTest, SavePageAsMHTML) {
773 static const int64 kFileSizeMin = 2758;
774 GURL url = NavigateToMockURL("b");
775 base::FilePath download_dir = DownloadPrefs::FromDownloadManager(
776 GetDownloadManager())->DownloadPath();
777 base::FilePath full_file_name = download_dir.AppendASCII(std::string(
778 "Test page for saving page feature.mhtml"));
779 SavePackageFilePicker::SetShouldPromptUser(false);
780 DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
781 &DownloadStoredProperly, url, full_file_name, -1,
782 DownloadItem::COMPLETE));
783 scoped_refptr<content::MessageLoopRunner> loop_runner(
784 new content::MessageLoopRunner);
785 SavePackageFinishedObserver observer(
786 content::BrowserContext::GetDownloadManager(browser()->profile()),
787 loop_runner->QuitClosure());
788 chrome::SavePage(browser());
789 loop_runner->Run();
790 ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
791 persisted.WaitForPersisted();
793 ASSERT_TRUE(base::PathExists(full_file_name));
794 int64 actual_file_size = -1;
795 EXPECT_TRUE(base::GetFileSize(full_file_name, &actual_file_size));
796 EXPECT_LE(kFileSizeMin, actual_file_size);
799 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SavePageBrowserTest_NonMHTML) {
800 SavePackageFilePicker::SetShouldPromptUser(false);
801 GURL url("data:text/plain,foo");
802 ui_test_utils::NavigateToURL(browser(), url);
803 scoped_refptr<content::MessageLoopRunner> loop_runner(
804 new content::MessageLoopRunner);
805 SavePackageFinishedObserver observer(
806 content::BrowserContext::GetDownloadManager(browser()->profile()),
807 loop_runner->QuitClosure());
808 chrome::SavePage(browser());
809 loop_runner->Run();
810 base::FilePath download_dir = DownloadPrefs::FromDownloadManager(
811 GetDownloadManager())->DownloadPath();
812 base::FilePath filename = download_dir.AppendASCII("dataurl.txt");
813 ASSERT_TRUE(base::PathExists(filename));
814 std::string contents;
815 EXPECT_TRUE(base::ReadFileToString(filename, &contents));
816 EXPECT_EQ("foo", contents);
819 } // namespace