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