diff options
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.cc | 36 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.h | 13 | ||||
-rw-r--r-- | chrome/browser/browser_encoding_browsertest.cc | 42 | ||||
-rw-r--r-- | chrome/browser/download/save_page_browsertest.cc | 113 | ||||
-rw-r--r-- | content/browser/download/download_manager_impl.cc | 6 | ||||
-rw-r--r-- | content/browser/download/download_manager_impl.h | 3 | ||||
-rw-r--r-- | content/browser/download/save_package.cc | 11 | ||||
-rw-r--r-- | content/public/browser/download_manager.h | 4 | ||||
-rw-r--r-- | content/public/browser/notification_types.h | 7 | ||||
-rw-r--r-- | content/public/test/test_utils.cc | 19 | ||||
-rw-r--r-- | content/public/test/test_utils.h | 9 |
11 files changed, 196 insertions, 67 deletions
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc index 051bf68..004398b 100644 --- a/chrome/browser/automation/automation_provider_observers.cc +++ b/chrome/browser/automation/automation_provider_observers.cc @@ -1707,31 +1707,31 @@ void OmniboxAcceptNotificationObserver::Observe( } SavePackageNotificationObserver::SavePackageNotificationObserver( - DownloadManager* download_manager, + content::DownloadManager* download_manager, AutomationProvider* automation, IPC::Message* reply_message) - : automation_(automation->AsWeakPtr()), + : download_manager_(download_manager), + automation_(automation->AsWeakPtr()), reply_message_(reply_message) { - content::Source<DownloadManager> source(download_manager); - registrar_.Add(this, content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, - source); + download_manager_->AddObserver(this); } -SavePackageNotificationObserver::~SavePackageNotificationObserver() {} +SavePackageNotificationObserver::~SavePackageNotificationObserver() { + download_manager_->RemoveObserver(this); +} -void SavePackageNotificationObserver::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - if (type == content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED) { - if (automation_) { - AutomationJSONReply(automation_, - reply_message_.release()).SendSuccess(NULL); - } - delete this; - } else { - NOTREACHED(); +void SavePackageNotificationObserver::OnSavePackageSuccessfullyFinished( + content::DownloadManager* manager, content::DownloadItem* item) { + if (automation_) { + AutomationJSONReply(automation_, + reply_message_.release()).SendSuccess(NULL); } + delete this; +} + +void SavePackageNotificationObserver::ManagerGoingDown( + content::DownloadManager* manager) { + delete this; } PageSnapshotTaker::PageSnapshotTaker(AutomationProvider* automation, diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index 6ba85ae..fec988a 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -1246,20 +1246,21 @@ class OmniboxAcceptNotificationObserver : public content::NotificationObserver { }; // Allows the automation provider to wait for a save package notification. -class SavePackageNotificationObserver : public content::NotificationObserver { +class SavePackageNotificationObserver +: public content::DownloadManager::Observer { public: SavePackageNotificationObserver(content::DownloadManager* download_manager, AutomationProvider* automation, IPC::Message* reply_message); virtual ~SavePackageNotificationObserver(); - // Overridden from content::NotificationObserver: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; + // Overridden from content::DownloadManager::Observer: + virtual void OnSavePackageSuccessfullyFinished( + content::DownloadManager* manager, content::DownloadItem* item) OVERRIDE; + virtual void ManagerGoingDown(content::DownloadManager* manager) OVERRIDE; private: - content::NotificationRegistrar registrar_; + content::DownloadManager* download_manager_; base::WeakPtr<AutomationProvider> automation_; scoped_ptr<IPC::Message> reply_message_; diff --git a/chrome/browser/browser_encoding_browsertest.cc b/chrome/browser/browser_encoding_browsertest.cc index 6b292bc..8c5fe94 100644 --- a/chrome/browser/browser_encoding_browsertest.cc +++ b/chrome/browser/browser_encoding_browsertest.cc @@ -16,6 +16,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_manager.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" @@ -65,6 +66,37 @@ const EncodingTestData kEncodingTestDatas[] = { { "windows-1258.html", "windows-1258" } }; +class SavePackageFinishedObserver : public content::DownloadManager::Observer { + public: + SavePackageFinishedObserver(content::DownloadManager* manager, + const base::Closure& callback) + : download_manager_(manager), + callback_(callback) { + download_manager_->AddObserver(this); + } + + virtual ~SavePackageFinishedObserver() { + if (download_manager_) + download_manager_->RemoveObserver(this); + } + + // DownloadManager::Observer: + virtual void OnSavePackageSuccessfullyFinished( + content::DownloadManager* manager, content::DownloadItem* item) OVERRIDE { + callback_.Run(); + } + virtual void ManagerGoingDown(content::DownloadManager* manager) OVERRIDE { + download_manager_->RemoveObserver(this); + download_manager_ = NULL; + } + + private: + content::DownloadManager* download_manager_; + base::Closure callback_; + + DISALLOW_COPY_AND_ASSIGN(SavePackageFinishedObserver); +}; + } // namespace using content::BrowserThread; @@ -86,13 +118,15 @@ class BrowserEncodingTest // We save the page as way of complete HTML file, which requires a directory // name to save sub resources in it. Although this test file does not have // sub resources, but the directory name is still required. - content::WindowedNotificationObserver observer( - content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, - content::NotificationService::AllSources()); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(browser()->profile()), + loop_runner->QuitClosure()); chrome::GetActiveWebContents(browser())->SavePage( full_file_name, temp_sub_resource_dir_, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML); - observer.Wait(); + loop_runner->Run(); FilePath expected_file_name = ui_test_utils::GetTestFilePath( FilePath(kTestDir), expected); diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc index 166a039..43c8781 100644 --- a/chrome/browser/download/save_page_browsertest.cc +++ b/chrome/browser/download/save_page_browsertest.cc @@ -53,6 +53,8 @@ using content::DownloadManager; using content::URLRequestMockHTTPJob; using content::WebContents; +namespace { + // Waits for an item record in the downloads database to match |filter|. See // DownloadStoredProperly() below for an example filter. class DownloadPersistedObserver : public DownloadHistory::Observer { @@ -240,6 +242,37 @@ class DownloadItemCreatedObserver : public DownloadManager::Observer { DISALLOW_COPY_AND_ASSIGN(DownloadItemCreatedObserver); }; +class SavePackageFinishedObserver : public content::DownloadManager::Observer { + public: + SavePackageFinishedObserver(content::DownloadManager* manager, + const base::Closure& callback) + : download_manager_(manager), + callback_(callback) { + download_manager_->AddObserver(this); + } + + virtual ~SavePackageFinishedObserver() { + if (download_manager_) + download_manager_->RemoveObserver(this); + } + + // DownloadManager::Observer: + virtual void OnSavePackageSuccessfullyFinished( + content::DownloadManager* manager, content::DownloadItem* item) OVERRIDE { + callback_.Run(); + } + virtual void ManagerGoingDown(content::DownloadManager* manager) OVERRIDE { + download_manager_->RemoveObserver(this); + download_manager_ = NULL; + } + + private: + content::DownloadManager* download_manager_; + base::Closure callback_; + + DISALLOW_COPY_AND_ASSIGN(SavePackageFinishedObserver); +}; + class SavePageBrowserTest : public InProcessBrowserTest { public: SavePageBrowserTest() {} @@ -283,14 +316,9 @@ class SavePageBrowserTest : public InProcessBrowserTest { // Returns true if and when there was a single download created, and its url // is |expected_url|. - bool WaitForSavePackageToFinish( + bool VerifySavePackageExpectations( Browser* browser, const GURL& expected_url) const { - content::WindowedNotificationObserver observer( - content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, - content::NotificationService::AllSources()); - observer.Wait(); - // Generally, there should only be one download item created // in all of these tests. If it's already here, grab it; if not, // wait for it to show up. @@ -307,9 +335,7 @@ class SavePageBrowserTest : public InProcessBrowserTest { return false; DownloadItem* download_item(items[0]); - return ((expected_url == download_item->GetOriginalUrl()) && - (expected_url == content::Details<DownloadItem>( - observer.details()).ptr()->GetOriginalUrl())); + return (expected_url == download_item->GetOriginalUrl()); } // Note on synchronization: @@ -358,9 +384,15 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveHTMLOnly) { DownloadPersistedObserver persisted(browser()->profile(), base::Bind( &DownloadStoredProperly, url, full_file_name, 1, DownloadItem::COMPLETE)); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(browser()->profile()), + loop_runner->QuitClosure()); ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir, content::SAVE_PAGE_TYPE_AS_ONLY_HTML)); - ASSERT_TRUE(WaitForSavePackageToFinish(browser(), url)); + loop_runner->Run(); + ASSERT_TRUE(VerifySavePackageExpectations(browser(), url)); persisted.WaitForPersisted(); EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible()); EXPECT_TRUE(file_util::PathExists(full_file_name)); @@ -454,9 +486,15 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveViewSourceHTMLOnly) { DownloadPersistedObserver persisted(browser()->profile(), base::Bind( &DownloadStoredProperly, actual_page_url, full_file_name, 1, DownloadItem::COMPLETE)); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(browser()->profile()), + loop_runner->QuitClosure()); ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir, content::SAVE_PAGE_TYPE_AS_ONLY_HTML)); - ASSERT_TRUE(WaitForSavePackageToFinish(browser(), actual_page_url)); + loop_runner->Run(); + ASSERT_TRUE(VerifySavePackageExpectations(browser(), actual_page_url)); persisted.WaitForPersisted(); EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible()); @@ -482,9 +520,15 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveCompleteHTML) { DownloadPersistedObserver persisted(browser()->profile(), base::Bind( &DownloadStoredProperly, url, full_file_name, 3, DownloadItem::COMPLETE)); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(browser()->profile()), + loop_runner->QuitClosure()); ASSERT_TRUE(GetCurrentTab(browser())->SavePage( full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML)); - ASSERT_TRUE(WaitForSavePackageToFinish(browser(), url)); + loop_runner->Run(); + ASSERT_TRUE(VerifySavePackageExpectations(browser(), url)); persisted.WaitForPersisted(); EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible()); @@ -530,10 +574,16 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, // Save the page before completion. FilePath full_file_name, dir; GetDestinationPaths("b", &full_file_name, &dir); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(incognito->profile()), + loop_runner->QuitClosure()); ASSERT_TRUE(GetCurrentTab(incognito)->SavePage( full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML)); - ASSERT_TRUE(WaitForSavePackageToFinish(incognito, url)); + loop_runner->Run(); + ASSERT_TRUE(VerifySavePackageExpectations(incognito, url)); // Confirm download shelf is visible. EXPECT_TRUE(incognito->window()->IsDownloadShelfVisible()); @@ -566,10 +616,16 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_FileNameFromPageTitle) { DownloadPersistedObserver persisted(browser()->profile(), base::Bind( &DownloadStoredProperly, url, full_file_name, 3, DownloadItem::COMPLETE)); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(browser()->profile()), + loop_runner->QuitClosure()); ASSERT_TRUE(GetCurrentTab(browser())->SavePage( full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML)); - ASSERT_TRUE(WaitForSavePackageToFinish(browser(), url)); + loop_runner->Run(); + ASSERT_TRUE(VerifySavePackageExpectations(browser(), url)); persisted.WaitForPersisted(); EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible()); @@ -601,10 +657,16 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_RemoveFromList) { DownloadPersistedObserver persisted(browser()->profile(), base::Bind( &DownloadStoredProperly, url, full_file_name, 1, DownloadItem::COMPLETE)); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(browser()->profile()), + loop_runner->QuitClosure()); ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir, content::SAVE_PAGE_TYPE_AS_ONLY_HTML)); - ASSERT_TRUE(WaitForSavePackageToFinish(browser(), url)); + loop_runner->Run(); + ASSERT_TRUE(VerifySavePackageExpectations(browser(), url)); persisted.WaitForPersisted(); EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible()); @@ -645,11 +707,13 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, CleanFilenameFromPageTitle) { ui_test_utils::NavigateToURL(browser(), url); SavePackageFilePicker::SetShouldPromptUser(false); - content::WindowedNotificationObserver observer( - content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, - content::NotificationService::AllSources()); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(browser()->profile()), + loop_runner->QuitClosure()); chrome::SavePage(browser()); - observer.Wait(); + loop_runner->Run(); EXPECT_TRUE(file_util::PathExists(full_file_name)); @@ -688,8 +752,14 @@ IN_PROC_BROWSER_TEST_F(SavePageAsMHTMLBrowserTest, SavePageAsMHTML) { DownloadPersistedObserver persisted(browser()->profile(), base::Bind( &DownloadStoredProperly, url, full_file_name, -1, DownloadItem::COMPLETE)); + scoped_refptr<content::MessageLoopRunner> loop_runner( + new content::MessageLoopRunner); + SavePackageFinishedObserver observer( + content::BrowserContext::GetDownloadManager(browser()->profile()), + loop_runner->QuitClosure()); chrome::SavePage(browser()); - ASSERT_TRUE(WaitForSavePackageToFinish(browser(), url)); + loop_runner->Run(); + ASSERT_TRUE(VerifySavePackageExpectations(browser(), url)); persisted.WaitForPersisted(); EXPECT_TRUE(file_util::PathExists(full_file_name)); @@ -697,3 +767,6 @@ IN_PROC_BROWSER_TEST_F(SavePageAsMHTMLBrowserTest, SavePageAsMHTML) { EXPECT_TRUE(file_util::GetFileSize(full_file_name, &actual_file_size)); EXPECT_LE(kFileSizeMin, actual_file_size); } + +} // namespace + diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index 35b43cf..1d028c3 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc @@ -485,6 +485,12 @@ DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( return download_item; } +void DownloadManagerImpl::OnSavePackageSuccessfullyFinished( + DownloadItem* download_item) { + FOR_EACH_OBSERVER(Observer, observers_, + OnSavePackageSuccessfullyFinished(this, download_item)); +} + void DownloadManagerImpl::CancelDownload(int32 download_id) { DownloadItem* download = GetDownload(download_id); if (!download || !download->IsInProgress()) diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h index de7ad5d..a967c55 100644 --- a/content/browser/download/download_manager_impl.h +++ b/content/browser/download/download_manager_impl.h @@ -47,6 +47,9 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager, const std::string& mime_type, DownloadItem::Observer* observer); + // Notifies DownloadManager about a successful completion of |download_item|. + void OnSavePackageSuccessfullyFinished(DownloadItem* download_item); + // DownloadManager functions. virtual void SetDelegate(DownloadManagerDelegate* delegate) OVERRIDE; virtual DownloadManagerDelegate* GetDelegate() const OVERRIDE; diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc index 1be1da4..c074d1e 100644 --- a/content/browser/download/save_package.cc +++ b/content/browser/download/save_package.cc @@ -1392,16 +1392,7 @@ void SavePackage::FinalizeDownloadEntry() { DCHECK(download_); DCHECK(download_manager_); - NotificationService::current()->Notify( - NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, - // We use the DownloadManager as the source as that's a - // central SavePackage related location that observers can - // get to if they want to wait for notifications for a - // particular BrowserContext. Alternatively, we could make - // it come from the WebContents, which would be more specific - // but less useful to (current) customers. - Source<DownloadManager>(download_manager_), - Details<DownloadItem>(download_)); + download_manager_->OnSavePackageSuccessfullyFinished(download_); StopObservation(); } diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h index 14dfac4..e7b03de 100644 --- a/content/public/browser/download_manager.h +++ b/content/public/browser/download_manager.h @@ -84,6 +84,10 @@ class CONTENT_EXPORT DownloadManager virtual void OnDownloadCreated( DownloadManager* manager, DownloadItem* item) {} + // A SavePackage has successfully finished. + virtual void OnSavePackageSuccessfullyFinished( + DownloadManager* manager, DownloadItem* item) {} + // Called when the DownloadManager is being destroyed to prevent Observers // from calling back to a stale pointer. virtual void ManagerGoingDown(DownloadManager* manager) {} diff --git a/content/public/browser/notification_types.h b/content/public/browser/notification_types.h index b70d05e..281a960 100644 --- a/content/public/browser/notification_types.h +++ b/content/public/browser/notification_types.h @@ -351,12 +351,7 @@ enum NotificationType { // in a Details<ChildProcessData>. NOTIFICATION_CHILD_INSTANCE_CREATED, - // Saved Pages ------------------------------------------------------------- - - // Sent when a SavePackage finishes successfully. The source is the - // SavePackage, and Details are a GURL containing address of downloaded - // page. - NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, + // Miscellaneous ------------------------------------------------------------- // Sent before the repost form warning is brought up. // The source is a NavigationController. diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc index 2e6b375..6d13f5a 100644 --- a/content/public/test/test_utils.cc +++ b/content/public/test/test_utils.cc @@ -94,13 +94,22 @@ base::Closure GetQuitTaskForRunLoop(base::RunLoop* run_loop) { kNumQuitDeferrals); } -MessageLoopRunner::MessageLoopRunner() { +MessageLoopRunner::MessageLoopRunner() + : loop_running_(false), + quit_closure_called_(false) { } MessageLoopRunner::~MessageLoopRunner() { } void MessageLoopRunner::Run() { + // Do not run the message loop if our quit closure has already been called. + // This helps in scenarios where the closure has a chance to run before + // we Run explicitly. + if (quit_closure_called_) + return; + + loop_running_ = true; RunThisRunLoop(&run_loop_); } @@ -109,7 +118,13 @@ base::Closure MessageLoopRunner::QuitClosure() { } void MessageLoopRunner::Quit() { - GetQuitTaskForRunLoop(&run_loop_).Run(); + quit_closure_called_ = true; + + // Only run the quit task if we are running the message loop. + if (loop_running_) { + GetQuitTaskForRunLoop(&run_loop_).Run(); + loop_running_ = false; + } } WindowedNotificationObserver::WindowedNotificationObserver( diff --git a/content/public/test/test_utils.h b/content/public/test/test_utils.h index f992b46..69325d2 100644 --- a/content/public/test/test_utils.h +++ b/content/public/test/test_utils.h @@ -48,7 +48,8 @@ class MessageLoopRunner : public base::RefCounted<MessageLoopRunner> { public: MessageLoopRunner(); - // Run the current MessageLoop. + // Run the current MessageLoop unless the quit closure + // has already been called. void Run(); // Quit the matching call to Run (nested MessageLoops are unaffected). @@ -65,6 +66,12 @@ class MessageLoopRunner : public base::RefCounted<MessageLoopRunner> { friend class base::RefCounted<MessageLoopRunner>; ~MessageLoopRunner(); + // True when the message loop is running. + bool loop_running_; + + // True after closure returned by |QuitClosure| has been called. + bool quit_closure_called_; + base::RunLoop run_loop_; DISALLOW_COPY_AND_ASSIGN(MessageLoopRunner); |