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