| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/chrome/browser/download/browser_download_service.h" |
| |
| #include <vector> |
| |
| #include "base/memory/ptr_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" |
| #import "ios/chrome/browser/download/ar_quick_look_tab_helper.h" |
| #import "ios/chrome/browser/download/download_manager_tab_helper.h" |
| #include "ios/chrome/browser/download/mime_type_util.h" |
| #import "ios/chrome/browser/download/pass_kit_tab_helper.h" |
| #import "ios/chrome/browser/download/vcard_tab_helper.h" |
| #import "ios/chrome/browser/ui/download/features.h" |
| #import "ios/web/public/download/download_controller.h" |
| #import "ios/web/public/download/download_task.h" |
| #import "ios/web/public/test/fakes/fake_download_task.h" |
| #import "ios/web/public/test/fakes/fake_web_state.h" |
| #include "ios/web/public/test/web_task_environment.h" |
| #include "testing/platform_test.h" |
| #include "url/gurl.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| namespace { |
| const char kUrl[] = "https://test.test/"; |
| const char16_t kUsdzFileName[] = u"important_file.usdz"; |
| const char16_t kRealityFileName[] = u"important_file.reality"; |
| |
| // Substitutes real TabHelper for testing. |
| template <class TabHelper> |
| class StubTabHelper : public TabHelper { |
| public: |
| // Overrides the method from web::WebStateUserData<TabHelper>. |
| static void CreateForWebState(web::WebState* web_state) { |
| web_state->SetUserData(TabHelper::UserDataKey(), |
| base::WrapUnique(new StubTabHelper(web_state))); |
| } |
| |
| // Adds the given task to tasks() lists. |
| void Download(std::unique_ptr<web::DownloadTask> task) override { |
| tasks_.push_back(std::move(task)); |
| } |
| |
| // Tasks added via Download() call. |
| using DownloadTasks = std::vector<std::unique_ptr<web::DownloadTask>>; |
| const DownloadTasks& tasks() const { return tasks_; } |
| |
| StubTabHelper(web::WebState* web_state) : TabHelper(web_state) {} |
| |
| private: |
| DownloadTasks tasks_; |
| }; |
| |
| } // namespace |
| |
| // Test fixture for testing BrowserDownloadService class. |
| class BrowserDownloadServiceTest : public PlatformTest { |
| protected: |
| BrowserDownloadServiceTest() |
| : browser_state_(TestChromeBrowserState::Builder().Build()) { |
| StubTabHelper<PassKitTabHelper>::CreateForWebState(&web_state_); |
| StubTabHelper<ARQuickLookTabHelper>::CreateForWebState(&web_state_); |
| StubTabHelper<VcardTabHelper>::CreateForWebState(&web_state_); |
| StubTabHelper<DownloadManagerTabHelper>::CreateForWebState(&web_state_); |
| web_state_.SetBrowserState(browser_state_.get()); |
| } |
| |
| web::DownloadController* download_controller() { |
| return web::DownloadController::FromBrowserState(browser_state_.get()); |
| } |
| |
| StubTabHelper<PassKitTabHelper>* pass_kit_tab_helper() { |
| return static_cast<StubTabHelper<PassKitTabHelper>*>( |
| PassKitTabHelper::FromWebState(&web_state_)); |
| } |
| |
| StubTabHelper<ARQuickLookTabHelper>* ar_quick_look_tab_helper() { |
| return static_cast<StubTabHelper<ARQuickLookTabHelper>*>( |
| ARQuickLookTabHelper::FromWebState(&web_state_)); |
| } |
| |
| StubTabHelper<VcardTabHelper>* vcard_tab_helper() { |
| return static_cast<StubTabHelper<VcardTabHelper>*>( |
| VcardTabHelper::FromWebState(&web_state_)); |
| } |
| |
| StubTabHelper<DownloadManagerTabHelper>* download_manager_tab_helper() { |
| return static_cast<StubTabHelper<DownloadManagerTabHelper>*>( |
| DownloadManagerTabHelper::FromWebState(&web_state_)); |
| } |
| |
| web::WebTaskEnvironment task_environment_; |
| std::unique_ptr<TestChromeBrowserState> browser_state_; |
| web::FakeWebState web_state_; |
| base::HistogramTester histogram_tester_; |
| }; |
| |
| // Tests that BrowserDownloadService downloads the task using |
| // PassKitTabHelper. |
| TEST_F(BrowserDownloadServiceTest, PkPassMimeType) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = |
| std::make_unique<web::FakeDownloadTask>(GURL(kUrl), kPkPassMimeType); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_EQ(1U, pass_kit_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, pass_kit_tab_helper()->tasks()[0].get()); |
| ASSERT_TRUE(download_manager_tab_helper()->tasks().empty()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>(DownloadMimeTypeResult::PkPass), |
| 1); |
| } |
| |
| // Tests that BrowserDownloadService uses ARQuickLookTabHelper for .USDZ |
| // extension. |
| TEST_F(BrowserDownloadServiceTest, UsdzExtension) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = std::make_unique<web::FakeDownloadTask>(GURL(kUrl), "other"); |
| task->SetSuggestedFilename(kUsdzFileName); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_EQ(1U, ar_quick_look_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, ar_quick_look_tab_helper()->tasks()[0].get()); |
| ASSERT_TRUE(download_manager_tab_helper()->tasks().empty()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>(DownloadMimeTypeResult::Other), |
| 1); |
| } |
| |
| // Tests that BrowserDownloadService uses ARQuickLookTabHelper for .REALITY |
| // extension. |
| TEST_F(BrowserDownloadServiceTest, RealityExtension) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = std::make_unique<web::FakeDownloadTask>(GURL(kUrl), "other"); |
| task->SetSuggestedFilename(kRealityFileName); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_EQ(1U, ar_quick_look_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, ar_quick_look_tab_helper()->tasks()[0].get()); |
| ASSERT_TRUE(download_manager_tab_helper()->tasks().empty()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>(DownloadMimeTypeResult::Other), |
| 1); |
| } |
| // Tests that BrowserDownloadService uses ARQuickLookTabHelper for USDZ Mime |
| // type. |
| TEST_F(BrowserDownloadServiceTest, UsdzMimeType) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = |
| std::make_unique<web::FakeDownloadTask>(GURL(kUrl), kUsdzMimeType); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_EQ(1U, ar_quick_look_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, ar_quick_look_tab_helper()->tasks()[0].get()); |
| ASSERT_TRUE(download_manager_tab_helper()->tasks().empty()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>( |
| DownloadMimeTypeResult::UniversalSceneDescription), |
| 1); |
| } |
| |
| // Tests that BrowserDownloadService uses ARQuickLookTabHelper for legacy USDZ |
| // Mime type. |
| TEST_F(BrowserDownloadServiceTest, LegacyUsdzMimeType) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = |
| std::make_unique<web::FakeDownloadTask>(GURL(kUrl), kLegacyUsdzMimeType); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_EQ(1U, ar_quick_look_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, ar_quick_look_tab_helper()->tasks()[0].get()); |
| ASSERT_TRUE(download_manager_tab_helper()->tasks().empty()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>( |
| DownloadMimeTypeResult::LegacyUniversalSceneDescription), |
| 1); |
| } |
| |
| // Tests that BrowserDownloadService uses ARQuickLookTabHelper for legacy Pixar |
| // USDZ Mime type. |
| TEST_F(BrowserDownloadServiceTest, LegacyPixarUsdzMimeType) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = std::make_unique<web::FakeDownloadTask>(GURL(kUrl), |
| kLegacyPixarUsdzMimeType); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_EQ(1U, ar_quick_look_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, ar_quick_look_tab_helper()->tasks()[0].get()); |
| ASSERT_TRUE(download_manager_tab_helper()->tasks().empty()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>( |
| DownloadMimeTypeResult::LegacyPixarUniversalSceneDescription), |
| 1); |
| } |
| |
| // Tests that BrowserDownloadService uses DownloadManagerTabHelper for PDF Mime |
| // Type. |
| TEST_F(BrowserDownloadServiceTest, PdfMimeType) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = |
| std::make_unique<web::FakeDownloadTask>(GURL(kUrl), "application/pdf"); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_TRUE(pass_kit_tab_helper()->tasks().empty()); |
| ASSERT_EQ(1U, download_manager_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, download_manager_tab_helper()->tasks()[0].get()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>(DownloadMimeTypeResult::Other), |
| 1); |
| } |
| |
| // Tests that BrowserDownloadService uses DownloadManagerTabHelper for Zip Mime |
| // Type. |
| TEST_F(BrowserDownloadServiceTest, ZipArchiveMimeType) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = |
| std::make_unique<web::FakeDownloadTask>(GURL(kUrl), kZipArchiveMimeType); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_TRUE(pass_kit_tab_helper()->tasks().empty()); |
| ASSERT_EQ(1U, download_manager_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, download_manager_tab_helper()->tasks()[0].get()); |
| histogram_tester_.ExpectUniqueSample("Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>( |
| DownloadMimeTypeResult::ZipArchive), |
| 1); |
| } |
| |
| // Tests that BrowserDownloadService uses DownloadManagerTabHelper for .exe Mime |
| // Type. |
| TEST_F(BrowserDownloadServiceTest, ExeMimeType) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = std::make_unique<web::FakeDownloadTask>( |
| GURL(kUrl), kMicrosoftApplicationMimeType); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_TRUE(pass_kit_tab_helper()->tasks().empty()); |
| ASSERT_EQ(1U, download_manager_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, download_manager_tab_helper()->tasks()[0].get()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>( |
| DownloadMimeTypeResult::MicrosoftApplication), |
| 1); |
| } |
| |
| // Tests that BrowserDownloadService uses DownloadManagerTabHelper for .apk Mime |
| // Type. |
| TEST_F(BrowserDownloadServiceTest, ApkMimeType) { |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = std::make_unique<web::FakeDownloadTask>( |
| GURL(kUrl), kAndroidPackageArchiveMimeType); |
| web::DownloadTask* task_ptr = task.get(); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_TRUE(pass_kit_tab_helper()->tasks().empty()); |
| ASSERT_EQ(1U, download_manager_tab_helper()->tasks().size()); |
| EXPECT_EQ(task_ptr, download_manager_tab_helper()->tasks()[0].get()); |
| histogram_tester_.ExpectUniqueSample( |
| "Download.IOSDownloadMimeType", |
| static_cast<base::HistogramBase::Sample>( |
| DownloadMimeTypeResult::AndroidPackageArchive), |
| 1); |
| } |
| |
| // Tests that the code doesn't crash if the download manager tab helper hasn't |
| // been created for this webstate. |
| TEST_F(BrowserDownloadServiceTest, NoDownloadManager) { |
| web::FakeWebState fake_web_state; |
| fake_web_state.SetBrowserState(browser_state_.get()); |
| |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = std::make_unique<web::FakeDownloadTask>(GURL(kUrl), "test/test"); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &fake_web_state, std::move(task)); |
| ASSERT_EQ(0U, download_manager_tab_helper()->tasks().size()); |
| } |
| |
| // Tests downloading a valid vcard file while the kill switch is enabled. |
| TEST_F(BrowserDownloadServiceTest, VCardKillSwitch) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeature(kVCardKillSwitch); |
| |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = |
| std::make_unique<web::FakeDownloadTask>(GURL(kUrl), kVcardMimeType); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_EQ(0U, vcard_tab_helper()->tasks().size()); |
| } |
| |
| // Tests downloading a valid AR file while the kill switch is enabled. |
| TEST_F(BrowserDownloadServiceTest, ARKillSwitch) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeature(kARKillSwitch); |
| |
| ASSERT_TRUE(download_controller()->GetDelegate()); |
| auto task = |
| std::make_unique<web::FakeDownloadTask>(GURL(kUrl), kUsdzMimeType); |
| download_controller()->GetDelegate()->OnDownloadCreated( |
| download_controller(), &web_state_, std::move(task)); |
| ASSERT_EQ(0U, ar_quick_look_tab_helper()->tasks().size()); |
| } |