| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/printing/print_management/printing_manager.h" |
| |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/scoped_observation.h" |
| #include "base/task/cancelable_task_tracker.h" |
| #include "base/test/test_mock_time_task_runner.h" |
| #include "chrome/browser/ash/printing/cups_print_job.h" |
| #include "chrome/browser/ash/printing/history/print_job_history_service.h" |
| #include "chrome/browser/ash/printing/history/print_job_history_service_impl.h" |
| #include "chrome/browser/ash/printing/history/test_print_job_database.h" |
| #include "chrome/browser/ash/printing/test_cups_print_job_manager.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chromeos/components/print_management/mojom/printing_manager.mojom.h" |
| #include "components/history/core/browser/history_service.h" |
| #include "components/history/core/test/history_service_test_util.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| namespace ash { |
| namespace printing { |
| namespace print_management { |
| namespace { |
| |
| using ::chromeos::printing::printing_manager::mojom::PrintJobInfoPtr; |
| |
| constexpr char kTitle[] = "title"; |
| const int kPagesNumber = 3; |
| |
| void VerifyPrintJobIsOngoing(const PrintJobInfoPtr& jobInfo) { |
| // An ongoing print job has a null |completed_info| and a non-null |
| // |active_print_job_info|. |
| EXPECT_FALSE(jobInfo->completed_info); |
| EXPECT_TRUE(jobInfo->active_print_job_info); |
| } |
| |
| void VerifyPrintJobIsCompleted(const PrintJobInfoPtr& jobInfo) { |
| // A completed print job has a non-null |completed_info| and a null |
| // |active_print_job_info|. |
| EXPECT_TRUE(jobInfo->completed_info); |
| EXPECT_FALSE(jobInfo->active_print_job_info); |
| } |
| |
| // Waits for OnURLsDeleted event and when run quits the supplied run loop. |
| class WaitForURLsDeletedObserver : public history::HistoryServiceObserver { |
| public: |
| explicit WaitForURLsDeletedObserver(base::RunLoop* runner) |
| : runner_(runner) {} |
| ~WaitForURLsDeletedObserver() override = default; |
| WaitForURLsDeletedObserver(const WaitForURLsDeletedObserver&) = delete; |
| WaitForURLsDeletedObserver& operator=(const WaitForURLsDeletedObserver&) = |
| delete; |
| |
| // history::HistoryServiceObserver: |
| void OnHistoryDeletions(history::HistoryService* service, |
| const history::DeletionInfo& deletion_info) override { |
| runner_->Quit(); |
| } |
| |
| private: |
| raw_ptr<base::RunLoop> runner_; |
| }; |
| |
| void WaitForURLsDeletedNotification(history::HistoryService* history_service) { |
| base::RunLoop runner; |
| WaitForURLsDeletedObserver observer(&runner); |
| base::ScopedObservation<history::HistoryService, |
| history::HistoryServiceObserver> |
| scoped_observer(&observer); |
| scoped_observer.Observe(history_service); |
| runner.Run(); |
| } |
| } // namespace |
| |
| class PrintingManagerTest : public ::testing::Test { |
| public: |
| PrintingManagerTest() { |
| test_prefs_.SetInitializationCompleted(); |
| PrintJobHistoryService::RegisterProfilePrefs(test_prefs_.registry()); |
| test_prefs_.registry()->RegisterBooleanPref( |
| prefs::kDeletePrintJobHistoryAllowed, true); |
| |
| print_job_manager_ = std::make_unique<TestCupsPrintJobManager>(&profile_); |
| auto print_job_database = std::make_unique<TestPrintJobDatabase>(); |
| print_job_history_service_ = std::make_unique<PrintJobHistoryServiceImpl>( |
| std::move(print_job_database), print_job_manager_.get(), &test_prefs_); |
| EXPECT_TRUE(history_dir_.CreateUniqueTempDir()); |
| local_history_ = |
| history::CreateHistoryService(history_dir_.GetPath(), true); |
| printing_manager_ = std::make_unique<PrintingManager>( |
| print_job_history_service_.get(), local_history_.get(), |
| print_job_manager_.get(), &test_prefs_); |
| mock_time_task_runner_ = |
| base::MakeRefCounted<base::TestMockTimeTaskRunner>(); |
| } |
| |
| void OnPrintJobsRetrieved(base::RepeatingClosure run_loop_closure, |
| std::vector<PrintJobInfoPtr> entries) { |
| entries_ = std::move(entries); |
| run_loop_closure.Run(); |
| } |
| |
| void OnDeleteAllPrintJobs(base::RepeatingClosure run_loop_closure, |
| bool expected_result, |
| bool success) { |
| EXPECT_EQ(expected_result, success); |
| run_loop_closure.Run(); |
| } |
| |
| void RunGetPrintJobs() { |
| base::RunLoop run_loop; |
| printing_manager_->GetPrintJobs( |
| base::BindOnce(&PrintingManagerTest::OnPrintJobsRetrieved, |
| base::Unretained(this), run_loop.QuitClosure())); |
| run_loop.Run(); |
| } |
| |
| void CreateCompletedPrintJob(int id) { |
| DCHECK(print_job_manager_); |
| auto print_job = CreateOngoingPrintJob(id); |
| print_job_manager_->CancelPrintJob(print_job.get()); |
| } |
| |
| std::unique_ptr<CupsPrintJob> CreateOngoingPrintJob(int id) { |
| auto print_job = std::make_unique<CupsPrintJob>( |
| chromeos::Printer(), id, kTitle, kPagesNumber, |
| ::printing::PrintJob::Source::kPrintPreview, |
| /*source_id=*/"", proto::PrintSettings()); |
| print_job_manager_->CreatePrintJob(print_job.get()); |
| return print_job; |
| } |
| |
| protected: |
| content::BrowserTaskEnvironment task_environment_; |
| // This cannot be declared after |print_job_manager| and |printing_manager| |
| // as we have to ensure that those services are destructed before this |
| // is destructed. |
| TestingPrefServiceSimple test_prefs_; |
| std::unique_ptr<TestCupsPrintJobManager> print_job_manager_; |
| std::unique_ptr<history::HistoryService> local_history_; |
| std::unique_ptr<PrintingManager> printing_manager_; |
| std::vector<PrintJobInfoPtr> entries_; |
| scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner_; |
| |
| private: |
| std::unique_ptr<PrintJobHistoryService> print_job_history_service_; |
| TestingProfile profile_; |
| base::ScopedTempDir history_dir_; |
| }; |
| |
| TEST_F(PrintingManagerTest, RetrieveOngoingPrintJob) { |
| // Assert no initial print jobs are ongoing or saved. |
| RunGetPrintJobs(); |
| ASSERT_EQ(0u, entries_.size()); |
| |
| auto print_job = CreateOngoingPrintJob(/*id=*/0); |
| |
| // Expect to have retrieved one ongoing print job. |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| VerifyPrintJobIsOngoing(entries_[0]); |
| |
| // Finish the print job and expect that it is now a completed print job. |
| print_job_manager_->CancelPrintJob(print_job.get()); |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| VerifyPrintJobIsCompleted(entries_[0]); |
| } |
| |
| TEST_F(PrintingManagerTest, RetrieveCompletedPrintJob) { |
| // Assert no initial print jobs are ongoing or saved. |
| RunGetPrintJobs(); |
| ASSERT_EQ(0u, entries_.size()); |
| |
| CreateCompletedPrintJob(/*id=*/0); |
| |
| // Expect to have retrieved one ongoing print job. |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| VerifyPrintJobIsCompleted(entries_[0]); |
| } |
| |
| TEST_F(PrintingManagerTest, RetrieveCompletedAndOngoingPrintJobs) { |
| // Assert no initial print jobs are ongoing or saved. |
| RunGetPrintJobs(); |
| ASSERT_EQ(0u, entries_.size()); |
| |
| // Create completed print job. |
| CreateCompletedPrintJob(/*id=*/0); |
| |
| // Create ongoing print job. |
| auto ongoing_print_job = CreateOngoingPrintJob(/*id=*/1); |
| |
| // Expect to have retrieved one ongoing print job. |
| RunGetPrintJobs(); |
| EXPECT_EQ(2u, entries_.size()); |
| VerifyPrintJobIsCompleted(entries_[0]); |
| VerifyPrintJobIsOngoing(entries_[1]); |
| } |
| |
| TEST_F(PrintingManagerTest, DeleteAllPrintJobs) { |
| // Assert no initial print jobs are ongoing or saved. |
| RunGetPrintJobs(); |
| ASSERT_EQ(0u, entries_.size()); |
| |
| CreateCompletedPrintJob(/*id=*/0); |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| |
| // Delete all print jobs. |
| base::RunLoop delete_all_print_jobs_run_loop; |
| printing_manager_->DeleteAllPrintJobs(base::BindOnce( |
| &PrintingManagerTest::OnDeleteAllPrintJobs, base::Unretained(this), |
| delete_all_print_jobs_run_loop.QuitClosure(), |
| /*expected_result=*/true)); |
| delete_all_print_jobs_run_loop.Run(); |
| |
| // Run GetPrintJobs again and verify that the print job has been deleted. |
| RunGetPrintJobs(); |
| EXPECT_EQ(0u, entries_.size()); |
| } |
| |
| TEST_F(PrintingManagerTest, DeleteAllPrintJobsPreventedByPolicy) { |
| test_prefs_.SetBoolean(prefs::kDeletePrintJobHistoryAllowed, false); |
| |
| // Assert no initial print jobs are ongoing or saved. |
| RunGetPrintJobs(); |
| ASSERT_EQ(0u, entries_.size()); |
| |
| CreateCompletedPrintJob(/*id=*/0); |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| |
| // Delete all print jobs. |
| base::RunLoop delete_all_print_jobs_run_loop; |
| printing_manager_->DeleteAllPrintJobs(base::BindOnce( |
| &PrintingManagerTest::OnDeleteAllPrintJobs, base::Unretained(this), |
| delete_all_print_jobs_run_loop.QuitClosure(), |
| /*expected_result=*/false)); |
| delete_all_print_jobs_run_loop.Run(); |
| |
| // Run GetPrintJobs again and verify that the print job has not been deleted. |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| } |
| |
| TEST_F(PrintingManagerTest, DeletingBrowserHistoryDeletesAllPrintJobs) { |
| // Assert no initial print jobs are ongoing or saved. |
| RunGetPrintJobs(); |
| ASSERT_EQ(0u, entries_.size()); |
| |
| // Store a print job. |
| CreateCompletedPrintJob(/*id=*/0); |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| |
| // Simulate deleting all history, expect print job history to also be deleted. |
| base::CancelableTaskTracker task_tracker; |
| local_history_->ExpireHistoryBetween( |
| std::set<GURL>(), history::kNoAppIdFilter, base::Time(), base::Time(), |
| /*user_initiated*/ true, base::DoNothing(), &task_tracker); |
| mock_time_task_runner_->RunUntilIdle(); |
| |
| WaitForURLsDeletedNotification(local_history_.get()); |
| |
| // Run GetPrintJobs again and verify that the print job has been deleted. |
| RunGetPrintJobs(); |
| EXPECT_EQ(0u, entries_.size()); |
| } |
| |
| TEST_F(PrintingManagerTest, PolicyPreventsDeletingBrowserHistoryDeletingJobs) { |
| test_prefs_.SetBoolean(prefs::kDeletePrintJobHistoryAllowed, false); |
| |
| // Assert no initial print jobs are ongoing or saved. |
| RunGetPrintJobs(); |
| ASSERT_EQ(0u, entries_.size()); |
| |
| // Store a print job. |
| CreateCompletedPrintJob(/*id=*/0); |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| |
| // Simulate deleting all history, expect print job history to not be deleted. |
| base::CancelableTaskTracker task_tracker; |
| local_history_->ExpireHistoryBetween( |
| std::set<GURL>(), history::kNoAppIdFilter, base::Time(), base::Time(), |
| /*user_initiated*/ true, base::DoNothing(), &task_tracker); |
| mock_time_task_runner_->RunUntilIdle(); |
| |
| WaitForURLsDeletedNotification(local_history_.get()); |
| |
| // Run GetPrintJobs again and verify that the print job has not been deleted. |
| RunGetPrintJobs(); |
| EXPECT_EQ(1u, entries_.size()); |
| } |
| |
| TEST_F(PrintingManagerTest, ResetReceiverOnBindInterface) { |
| // This test simulates a user refreshing the WebUI page. The receiver should |
| // be reset before binding the new receiver. Otherwise we would get a DCHECK |
| // error from mojo::Receiver |
| mojo::Remote< |
| chromeos::printing::printing_manager::mojom::PrintingMetadataProvider> |
| remote; |
| printing_manager_->BindInterface(remote.BindNewPipeAndPassReceiver()); |
| base::RunLoop().RunUntilIdle(); |
| |
| remote.reset(); |
| |
| printing_manager_->BindInterface(remote.BindNewPipeAndPassReceiver()); |
| base::RunLoop().RunUntilIdle(); |
| } |
| } // namespace print_management |
| } // namespace printing |
| } // namespace ash |