Commit 2d4c8453 authored by Moe Ahmadi's avatar Moe Ahmadi Committed by Commit Bot

[AR][IOS] AR Quick Look integration

- Adds a feature and corresponding flags in order to gate the integration.
- Modifies ARQuickLookTabHelper to inform delegate only if download was
  successful.
- Hooks up ARQuickLookTabHelper in DownloadServiceManager.
- Sets up ARQuickLookCoordinator and ARQuickLookTabHelper in browser
  coordinator.
- Replaces the test USDZ file with a smaller one.
- Adds EG tests.

Bug: 908696
Change-Id: I37482d356b2e5db5ac09f46df957a3b0cdc48879
Reviewed-on: https://chromium-review.googlesource.com/c/1351980
Commit-Queue: Moe Ahmadi <mahmadi@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612564}
parent f0a854a2
...@@ -122,6 +122,7 @@ source_set("browser") { ...@@ -122,6 +122,7 @@ source_set("browser") {
"//ios/chrome/browser/browsing_data:feature_flags", "//ios/chrome/browser/browsing_data:feature_flags",
"//ios/chrome/browser/crash_report:flags", "//ios/chrome/browser/crash_report:flags",
"//ios/chrome/browser/download", "//ios/chrome/browser/download",
"//ios/chrome/browser/download:features",
"//ios/chrome/browser/drag_and_drop", "//ios/chrome/browser/drag_and_drop",
"//ios/chrome/browser/itunes_urls", "//ios/chrome/browser/itunes_urls",
"//ios/chrome/browser/mailto:feature_flags", "//ios/chrome/browser/mailto:feature_flags",
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "ios/chrome/browser/browsing_data/browsing_data_features.h" #include "ios/chrome/browser/browsing_data/browsing_data_features.h"
#include "ios/chrome/browser/chrome_switches.h" #include "ios/chrome/browser/chrome_switches.h"
#include "ios/chrome/browser/crash_report/crash_report_flags.h" #include "ios/chrome/browser/crash_report/crash_report_flags.h"
#include "ios/chrome/browser/download/features.h"
#include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h" #include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h"
#include "ios/chrome/browser/ios_chrome_flag_descriptions.h" #include "ios/chrome/browser/ios_chrome_flag_descriptions.h"
#include "ios/chrome/browser/itunes_urls/itunes_urls_flag.h" #include "ios/chrome/browser/itunes_urls/itunes_urls_flag.h"
...@@ -215,6 +216,9 @@ const flags_ui::FeatureEntry kFeatureEntries[] = { ...@@ -215,6 +216,9 @@ const flags_ui::FeatureEntry kFeatureEntries[] = {
feature_engagement::kIPHDemoMode, feature_engagement::kIPHDemoMode,
feature_engagement::kIPHDemoModeChoiceVariations, feature_engagement::kIPHDemoModeChoiceVariations,
"IPH_DemoMode")}, "IPH_DemoMode")},
{"preview-usdz", flag_descriptions::kUsdzPreviewName,
flag_descriptions::kUsdzPreviewDescription, flags_ui::kOsIos,
FEATURE_VALUE_TYPE(download::kUsdzPreview)},
{"use-ddljson-api", flag_descriptions::kUseDdljsonApiName, {"use-ddljson-api", flag_descriptions::kUseDdljsonApiName,
flag_descriptions::kUseDdljsonApiDescription, flags_ui::kOsIos, flag_descriptions::kUseDdljsonApiDescription, flags_ui::kOsIos,
MULTI_VALUE_TYPE(kUseDdljsonApiChoices)}, MULTI_VALUE_TYPE(kUseDdljsonApiChoices)},
......
...@@ -29,6 +29,7 @@ source_set("download") { ...@@ -29,6 +29,7 @@ source_set("download") {
] ]
deps = [ deps = [
":features",
"//base", "//base",
"//components/keyed_service/core", "//components/keyed_service/core",
"//components/keyed_service/ios", "//components/keyed_service/ios",
...@@ -48,6 +49,19 @@ source_set("download") { ...@@ -48,6 +49,19 @@ source_set("download") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
} }
source_set("features") {
sources = [
"features.h",
"features.mm",
]
deps = [
"//base",
]
configs += [ "//build/config/compiler:enable_arc" ]
}
source_set("unit_tests") { source_set("unit_tests") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
testonly = true testonly = true
...@@ -65,6 +79,7 @@ source_set("unit_tests") { ...@@ -65,6 +79,7 @@ source_set("unit_tests") {
"//base/test:test_support", "//base/test:test_support",
"//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/download", "//ios/chrome/browser/download",
"//ios/chrome/browser/download:features",
"//ios/chrome/browser/ui:network_activity_indicator_manager", "//ios/chrome/browser/ui:network_activity_indicator_manager",
"//ios/chrome/test/fakes", "//ios/chrome/test/fakes",
"//ios/web/public", "//ios/web/public",
...@@ -81,8 +96,8 @@ source_set("test_support") { ...@@ -81,8 +96,8 @@ source_set("test_support") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
testonly = true testonly = true
sources = [ sources = [
"pass_kit_test_util.cc", "download_test_util.cc",
"pass_kit_test_util.h", "download_test_util.h",
] ]
deps = [ deps = [
"//base", "//base",
......
...@@ -122,6 +122,12 @@ void ARQuickLookTabHelper::Download( ...@@ -122,6 +122,12 @@ void ARQuickLookTabHelper::Download(
void ARQuickLookTabHelper::DidFinishDownload() { void ARQuickLookTabHelper::DidFinishDownload() {
DCHECK_EQ(download_task_->GetState(), web::DownloadTask::State::kComplete); DCHECK_EQ(download_task_->GetState(), web::DownloadTask::State::kComplete);
// Inform the delegate only if the download has been successful.
if (download_task_->GetHttpCode() == 401 ||
download_task_->GetHttpCode() == 403 || download_task_->GetErrorCode() ||
download_task_->GetMimeType() != kUsdzMimeType) {
return;
}
net::URLFetcherFileWriter* file_writer = net::URLFetcherFileWriter* file_writer =
download_task_->GetResponseWriter()->AsFileWriter(); download_task_->GetResponseWriter()->AsFileWriter();
......
...@@ -194,8 +194,7 @@ TEST_F(ARQuickLookTabHelperTest, MimeTypeChange) { ...@@ -194,8 +194,7 @@ TEST_F(ARQuickLookTabHelperTest, MimeTypeChange) {
})); }));
task_ptr->SetMimeType("text/html"); task_ptr->SetMimeType("text/html");
task_ptr->SetDone(true); task_ptr->SetDone(true);
EXPECT_EQ(1U, delegate().fileURLs.count); EXPECT_EQ(0U, delegate().fileURLs.count);
EXPECT_TRUE([delegate().fileURLs.firstObject isKindOfClass:[NSURL class]]);
histogram_tester()->ExpectBucketCount( histogram_tester()->ExpectBucketCount(
kHistogramName, kHistogramName,
...@@ -227,8 +226,7 @@ TEST_F(ARQuickLookTabHelperTest, DownloadError) { ...@@ -227,8 +226,7 @@ TEST_F(ARQuickLookTabHelperTest, DownloadError) {
})); }));
task_ptr->SetErrorCode(net::ERR_INTERNET_DISCONNECTED); task_ptr->SetErrorCode(net::ERR_INTERNET_DISCONNECTED);
task_ptr->SetDone(true); task_ptr->SetDone(true);
EXPECT_EQ(1U, delegate().fileURLs.count); EXPECT_EQ(0U, delegate().fileURLs.count);
EXPECT_TRUE([delegate().fileURLs.firstObject isKindOfClass:[NSURL class]]);
histogram_tester()->ExpectBucketCount( histogram_tester()->ExpectBucketCount(
kHistogramName, kHistogramName,
...@@ -260,8 +258,7 @@ TEST_F(ARQuickLookTabHelperTest, UnauthorizedHttpResponse) { ...@@ -260,8 +258,7 @@ TEST_F(ARQuickLookTabHelperTest, UnauthorizedHttpResponse) {
})); }));
task_ptr->SetHttpCode(401); task_ptr->SetHttpCode(401);
task_ptr->SetDone(true); task_ptr->SetDone(true);
EXPECT_EQ(1U, delegate().fileURLs.count); EXPECT_EQ(0U, delegate().fileURLs.count);
EXPECT_TRUE([delegate().fileURLs.firstObject isKindOfClass:[NSURL class]]);
histogram_tester()->ExpectBucketCount( histogram_tester()->ExpectBucketCount(
kHistogramName, kHistogramName,
...@@ -293,8 +290,7 @@ TEST_F(ARQuickLookTabHelperTest, ForbiddenHttpResponse) { ...@@ -293,8 +290,7 @@ TEST_F(ARQuickLookTabHelperTest, ForbiddenHttpResponse) {
})); }));
task_ptr->SetHttpCode(403); task_ptr->SetHttpCode(403);
task_ptr->SetDone(true); task_ptr->SetDone(true);
EXPECT_EQ(1U, delegate().fileURLs.count); EXPECT_EQ(0U, delegate().fileURLs.count);
EXPECT_TRUE([delegate().fileURLs.firstObject isKindOfClass:[NSURL class]]);
histogram_tester()->ExpectBucketCount( histogram_tester()->ExpectBucketCount(
kHistogramName, kHistogramName,
......
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
#include "ios/chrome/browser/download/browser_download_service.h" #include "ios/chrome/browser/download/browser_download_service.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#import "ios/chrome/browser/download/ar_quick_look_tab_helper.h"
#import "ios/chrome/browser/download/download_manager_tab_helper.h" #import "ios/chrome/browser/download/download_manager_tab_helper.h"
#import "ios/chrome/browser/download/features.h"
#include "ios/chrome/browser/download/pass_kit_mime_type.h" #include "ios/chrome/browser/download/pass_kit_mime_type.h"
#import "ios/chrome/browser/download/pass_kit_tab_helper.h" #import "ios/chrome/browser/download/pass_kit_tab_helper.h"
#include "ios/chrome/browser/download/usdz_mime_type.h"
#import "ios/web/public/download/download_controller.h" #import "ios/web/public/download/download_controller.h"
#import "ios/web/public/download/download_task.h" #import "ios/web/public/download/download_task.h"
...@@ -39,7 +42,7 @@ DownloadMimeTypeResult GetUmaResult(const std::string& mime_type) { ...@@ -39,7 +42,7 @@ DownloadMimeTypeResult GetUmaResult(const std::string& mime_type) {
if (mime_type == "text/calendar") if (mime_type == "text/calendar")
return DownloadMimeTypeResult::iCalendar; return DownloadMimeTypeResult::iCalendar;
if (mime_type == "model/usd") if (mime_type == kUsdzMimeType)
return DownloadMimeTypeResult::UniversalSceneDescription; return DownloadMimeTypeResult::UniversalSceneDescription;
return DownloadMimeTypeResult::Other; return DownloadMimeTypeResult::Other;
...@@ -72,6 +75,13 @@ void BrowserDownloadService::OnDownloadCreated( ...@@ -72,6 +75,13 @@ void BrowserDownloadService::OnDownloadCreated(
if (tab_helper) { if (tab_helper) {
tab_helper->Download(std::move(task)); tab_helper->Download(std::move(task));
} }
} else if (task->GetMimeType() == kUsdzMimeType &&
download::IsUsdzPreviewEnabled()) {
ARQuickLookTabHelper* tab_helper =
ARQuickLookTabHelper::FromWebState(web_state);
if (tab_helper) {
tab_helper->Download(std::move(task));
}
} else { } else {
DownloadManagerTabHelper* tab_helper = DownloadManagerTabHelper* tab_helper =
DownloadManagerTabHelper::FromWebState(web_state); DownloadManagerTabHelper::FromWebState(web_state);
......
...@@ -8,10 +8,14 @@ ...@@ -8,10 +8,14 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/test/metrics/histogram_tester.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" #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" #import "ios/chrome/browser/download/download_manager_tab_helper.h"
#import "ios/chrome/browser/download/features.h"
#include "ios/chrome/browser/download/pass_kit_mime_type.h" #include "ios/chrome/browser/download/pass_kit_mime_type.h"
#import "ios/chrome/browser/download/pass_kit_tab_helper.h" #import "ios/chrome/browser/download/pass_kit_tab_helper.h"
#include "ios/chrome/browser/download/usdz_mime_type.h"
#import "ios/web/public/download/download_controller.h" #import "ios/web/public/download/download_controller.h"
#import "ios/web/public/download/download_task.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_download_task.h"
...@@ -61,7 +65,10 @@ class BrowserDownloadServiceTest : public PlatformTest { ...@@ -61,7 +65,10 @@ class BrowserDownloadServiceTest : public PlatformTest {
protected: protected:
BrowserDownloadServiceTest() BrowserDownloadServiceTest()
: browser_state_(browser_state_builder_.Build()) { : browser_state_(browser_state_builder_.Build()) {
scoped_feature_list_.InitAndEnableFeature(download::kUsdzPreview);
StubTabHelper<PassKitTabHelper>::CreateForWebState(&web_state_); StubTabHelper<PassKitTabHelper>::CreateForWebState(&web_state_);
StubTabHelper<ARQuickLookTabHelper>::CreateForWebState(&web_state_);
StubTabHelper<DownloadManagerTabHelper>::CreateForWebState(&web_state_); StubTabHelper<DownloadManagerTabHelper>::CreateForWebState(&web_state_);
// BrowserDownloadServiceFactory sets its service as // BrowserDownloadServiceFactory sets its service as
...@@ -89,6 +96,11 @@ class BrowserDownloadServiceTest : public PlatformTest { ...@@ -89,6 +96,11 @@ class BrowserDownloadServiceTest : public PlatformTest {
PassKitTabHelper::FromWebState(&web_state_)); PassKitTabHelper::FromWebState(&web_state_));
} }
StubTabHelper<ARQuickLookTabHelper>* ar_quick_look_tab_helper() {
return static_cast<StubTabHelper<ARQuickLookTabHelper>*>(
ARQuickLookTabHelper::FromWebState(&web_state_));
}
StubTabHelper<DownloadManagerTabHelper>* download_manager_tab_helper() { StubTabHelper<DownloadManagerTabHelper>* download_manager_tab_helper() {
return static_cast<StubTabHelper<DownloadManagerTabHelper>*>( return static_cast<StubTabHelper<DownloadManagerTabHelper>*>(
DownloadManagerTabHelper::FromWebState(&web_state_)); DownloadManagerTabHelper::FromWebState(&web_state_));
...@@ -101,6 +113,7 @@ class BrowserDownloadServiceTest : public PlatformTest { ...@@ -101,6 +113,7 @@ class BrowserDownloadServiceTest : public PlatformTest {
std::unique_ptr<BrowserDownloadService> service_; std::unique_ptr<BrowserDownloadService> service_;
web::TestWebState web_state_; web::TestWebState web_state_;
base::HistogramTester histogram_tester_; base::HistogramTester histogram_tester_;
base::test::ScopedFeatureList scoped_feature_list_;
}; };
// Tests that BrowserDownloadService downloads the task using // Tests that BrowserDownloadService downloads the task using
...@@ -121,6 +134,31 @@ TEST_F(BrowserDownloadServiceTest, PkPassMimeType) { ...@@ -121,6 +134,31 @@ TEST_F(BrowserDownloadServiceTest, PkPassMimeType) {
1); 1);
} }
// Tests that BrowserDownloadService downloads the task using
// ARQuickLookTabHelper.
TEST_F(BrowserDownloadServiceTest, UsdzMimeType) {
if (!download::IsUsdzPreviewEnabled()) {
// Disabled on iOS versions below 12 because QLPreviewController is not
// available.
return;
}
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 DownloadManagerTabHelper for PDF Mime // Tests that BrowserDownloadService uses DownloadManagerTabHelper for PDF Mime
// Type. // Type.
TEST_F(BrowserDownloadServiceTest, PdfMimeType) { TEST_F(BrowserDownloadServiceTest, PdfMimeType) {
......
// Copyright 2017 The Chromium Authors. All rights reserved. // Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "ios/chrome/browser/download/pass_kit_test_util.h" #include "ios/chrome/browser/download/download_test_util.h"
#include "base/base_paths.h" #include "base/base_paths.h"
#include "base/files/file.h" #include "base/files/file.h"
...@@ -11,15 +11,21 @@ ...@@ -11,15 +11,21 @@
namespace testing { namespace testing {
std::string GetTestPass() { const char kPkPassFilePath[] =
"ios/testing/data/http_server_files/generic.pkpass";
const char kUsdzFilePath[] = "ios/testing/data/http_server_files/redchair.usdz";
std::string GetTestFileContents(const char* file_path) {
base::FilePath path; base::FilePath path;
base::PathService::Get(base::DIR_MODULE, &path); base::PathService::Get(base::DIR_MODULE, &path);
const char kFilePath[] = "ios/testing/data/http_server_files/generic.pkpass"; path = path.Append(FILE_PATH_LITERAL(file_path));
path = path.Append(FILE_PATH_LITERAL(kFilePath));
base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
char pass_kit_data[file.GetLength()]; size_t size_to_read = file.GetLength();
file.ReadAtCurrentPos(pass_kit_data, file.GetLength()); std::string contents;
return std::string(pass_kit_data, file.GetLength()); contents.resize(size_to_read);
size_t size_read = file.ReadAtCurrentPos(&contents[0], size_to_read);
contents.resize(size_read);
return contents;
} }
} // namespace testing } // namespace testing
// Copyright 2018 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.
#ifndef IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TEST_UTIL_H_
#define IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TEST_UTIL_H_
#include <string>
namespace testing {
extern const char kPkPassFilePath[];
extern const char kUsdzFilePath[];
// Returns contents of the test file at the given relative path in the chrome
// test directory.
std::string GetTestFileContents(const char* file_path);
} // namespace testing
#endif // IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TEST_UTIL_H_
// Copyright 2018 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.
#ifndef IOS_CHROME_BROWSER_DOWNLOAD_FEATURES_H_
#define IOS_CHROME_BROWSER_DOWNLOAD_FEATURES_H_
#include "base/feature_list.h"
namespace download {
extern const base::Feature kUsdzPreview;
// Returns whether USDZ AR Quick Look is enabled.
bool IsUsdzPreviewEnabled();
} // namespace download
#endif // IOS_CHROME_BROWSER_DOWNLOAD_FEATURES_H_
// Copyright 2018 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 <Foundation/Foundation.h>
#include "ios/chrome/browser/download/features.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace download {
// Controls previewing USDZ format 3D models in AR Quick Look.
const base::Feature kUsdzPreview{"USDZPreview",
base::FEATURE_ENABLED_BY_DEFAULT};
// Returns whether AR Quick Look in enabled.
bool IsUsdzPreviewEnabled() {
if (@available(iOS 12, *)) {
return base::FeatureList::IsEnabled(kUsdzPreview);
}
return false;
}
} // namespace download
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/histogram_tester.h"
#include "ios/chrome/browser/download/download_test_util.h"
#include "ios/chrome/browser/download/pass_kit_mime_type.h" #include "ios/chrome/browser/download/pass_kit_mime_type.h"
#include "ios/chrome/browser/download/pass_kit_test_util.h"
#import "ios/chrome/test/fakes/fake_pass_kit_tab_helper_delegate.h" #import "ios/chrome/test/fakes/fake_pass_kit_tab_helper_delegate.h"
#import "ios/web/public/test/fakes/fake_download_task.h" #import "ios/web/public/test/fakes/fake_download_task.h"
#import "ios/web/public/test/fakes/test_web_state.h" #import "ios/web/public/test/fakes/test_web_state.h"
...@@ -99,7 +99,8 @@ TEST_F(PassKitTabHelperTest, ValidPassKitFile) { ...@@ -99,7 +99,8 @@ TEST_F(PassKitTabHelperTest, ValidPassKitFile) {
web::FakeDownloadTask* task_ptr = task.get(); web::FakeDownloadTask* task_ptr = task.get();
tab_helper()->Download(std::move(task)); tab_helper()->Download(std::move(task));
std::string pass_data = testing::GetTestPass(); std::string pass_data =
testing::GetTestFileContents(testing::kPkPassFilePath);
auto buffer = base::MakeRefCounted<net::IOBuffer>(pass_data.size()); auto buffer = base::MakeRefCounted<net::IOBuffer>(pass_data.size());
memcpy(buffer->data(), pass_data.c_str(), pass_data.size()); memcpy(buffer->data(), pass_data.c_str(), pass_data.size());
// Writing to URLFetcherStringWriter, which is used by PassKitTabHelper is // Writing to URLFetcherStringWriter, which is used by PassKitTabHelper is
......
// 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.
#ifndef IOS_CHROME_BROWSER_DOWNLOAD_PASS_KIT_TEST_UTIL_H_
#define IOS_CHROME_BROWSER_DOWNLOAD_PASS_KIT_TEST_UTIL_H_
#include <string>
namespace testing {
// Returns the content of a test pkpass file.
std::string GetTestPass();
} // namespace testing
#endif // IOS_CHROME_BROWSER_DOWNLOAD_PASS_KIT_TEST_UTIL_H_
...@@ -352,6 +352,10 @@ const char kForceUnifiedConsentBumpDescription[] = ...@@ -352,6 +352,10 @@ const char kForceUnifiedConsentBumpDescription[] =
"Force the unified consent bump UI to be shown on every start-up. This " "Force the unified consent bump UI to be shown on every start-up. This "
"flag is for debug purpose, to test the UI."; "flag is for debug purpose, to test the UI.";
const char kUsdzPreviewName[] = "Preview USDZ format 3D models";
const char kUsdzPreviewDescription[] =
"Enables previewing USDZ format 3D models in AR Quick Look.";
const char kUseDdljsonApiName[] = "Use new ddljson API for Doodles"; const char kUseDdljsonApiName[] = "Use new ddljson API for Doodles";
const char kUseDdljsonApiDescription[] = const char kUseDdljsonApiDescription[] =
"Enables the new ddljson API to fetch Doodles for the NTP."; "Enables the new ddljson API to fetch Doodles for the NTP.";
......
...@@ -287,6 +287,10 @@ extern const char kUseMultiloginEndpointDescription[]; ...@@ -287,6 +287,10 @@ extern const char kUseMultiloginEndpointDescription[];
extern const char kForceUnifiedConsentBumpName[]; extern const char kForceUnifiedConsentBumpName[];
extern const char kForceUnifiedConsentBumpDescription[]; extern const char kForceUnifiedConsentBumpDescription[];
// Title and description for the flag to enable previewing USDZ 3 model files.
extern const char kUsdzPreviewName[];
extern const char kUsdzPreviewDescription[];
// Title and description for the flag to enable the ddljson Doodle API. // Title and description for the flag to enable the ddljson Doodle API.
extern const char kUseDdljsonApiName[]; extern const char kUseDdljsonApiName[];
extern const char kUseDdljsonApiDescription[]; extern const char kUseDdljsonApiDescription[];
......
...@@ -107,6 +107,7 @@ source_set("eg_tests") { ...@@ -107,6 +107,7 @@ source_set("eg_tests") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
testonly = true testonly = true
sources = [ sources = [
"ar_quick_look_egtest.mm",
"download_manager_egtest.mm", "download_manager_egtest.mm",
"pass_kit_egtest.mm", "pass_kit_egtest.mm",
] ]
...@@ -118,6 +119,7 @@ source_set("eg_tests") { ...@@ -118,6 +119,7 @@ source_set("eg_tests") {
"//ios/chrome/app/strings", "//ios/chrome/app/strings",
"//ios/chrome/browser:browser", "//ios/chrome/browser:browser",
"//ios/chrome/browser/download", "//ios/chrome/browser/download",
"//ios/chrome/browser/download:features",
"//ios/chrome/browser/download:test_support", "//ios/chrome/browser/download:test_support",
"//ios/chrome/browser/ui:ui_internal", "//ios/chrome/browser/ui:ui_internal",
"//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/util",
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h" #import "base/test/ios/wait_util.h"
#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/histogram_tester.h"
#include "ios/chrome/browser/download/download_test_util.h"
#include "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/browser/ui/util/ui_util.h"
#import "ios/chrome/test/scoped_key_window.h" #import "ios/chrome/test/scoped_key_window.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -28,11 +29,9 @@ namespace { ...@@ -28,11 +29,9 @@ namespace {
// Returns the absolute path for the test file in the test data directory. // Returns the absolute path for the test file in the test data directory.
base::FilePath GetTestFilePath() { base::FilePath GetTestFilePath() {
const char kValidFilePath[] =
"ios/testing/data/http_server_files/retrotv.usdz";
base::FilePath file_path; base::FilePath file_path;
base::PathService::Get(base::DIR_MODULE, &file_path); base::PathService::Get(base::DIR_MODULE, &file_path);
file_path = file_path.Append(FILE_PATH_LITERAL(kValidFilePath)); file_path = file_path.Append(FILE_PATH_LITERAL(testing::kUsdzFilePath));
return file_path; return file_path;
} }
......
// Copyright 2018 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 <EarlGrey/EarlGrey.h>
#import <QuickLook/QuickLook.h>
#include <memory>
#import "base/test/ios/wait_util.h"
#import "ios/chrome/app/main_controller.h"
#include "ios/chrome/browser/download/download_test_util.h"
#include "ios/chrome/browser/download/features.h"
#include "ios/chrome/browser/download/usdz_mime_type.h"
#import "ios/chrome/browser/ui/browser_view_controller.h"
#include "ios/chrome/browser/ui/util/ui_util.h"
#import "ios/chrome/test/app/chrome_test_util.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using base::test::ios::WaitUntilConditionOrTimeout;
using base::test::ios::kWaitForDownloadTimeout;
using base::test::ios::kWaitForUIElementTimeout;
using chrome_test_util::GetMainController;
namespace {
// USDZ landing page and download request handler.
std::unique_ptr<net::test_server::HttpResponse> GetResponse(
const net::test_server::HttpRequest& request) {
auto result = std::make_unique<net::test_server::BasicHttpResponse>();
result->set_code(net::HTTP_OK);
if (request.GetURL().path() == "/") {
result->set_content(
"<a id='forbidden' href='/forbidden'>Forbidden</a>"
"<a id='unauthorized' href='/unauthorized'>Unauthorized</a>"
"<a id='changing-mime-type' href='/changing-mime-type'>Changing Mime "
"Type</a>"
"<a id='good' href='/good'>Good</a>");
return result;
}
result->AddCustomHeader("Content-Type", kUsdzMimeType);
result->set_content(testing::GetTestFileContents(testing::kUsdzFilePath));
if (request.GetURL().path() == "/forbidden") {
result->set_code(net::HTTP_FORBIDDEN);
} else if (request.GetURL().path() == "/unauthorized") {
result->set_code(net::HTTP_UNAUTHORIZED);
} else if (request.GetURL().path() == "/changing-mime-type") {
result->AddCustomHeader("Content-Type", "unkown");
}
return result;
}
} // namespace
// Tests previewing USDZ format files.
@interface ARQuickLookEGTest : ChromeTestCase
@end
@implementation ARQuickLookEGTest
- (void)setUp {
[super setUp];
self.testServer->RegisterRequestHandler(base::BindRepeating(&GetResponse));
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
}
// Tests that QLPreviewController is shown for sucessfully downloaded USDZ file.
- (void)testDownloadUsdz {
if (!download::IsUsdzPreviewEnabled()) {
EARL_GREY_TEST_SKIPPED(
@"Disabled if 'USDZPreview' feature is disabled or on iOS versions "
"below 12 because QLPreviewController is not available.");
}
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGrey waitForWebViewContainingText:"Good"];
[ChromeEarlGrey tapWebViewElementWithID:@"good"];
// QLPreviewController UI is rendered out of host process so EarlGrey matcher
// can not find QLPreviewController UI. Instead this test relies on view
// controller presentation as the signal that QLPreviewController UI is shown.
UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
bool shown = WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{
UIViewController* presentedController = BVC.presentedViewController;
return [presentedController class] == [QLPreviewController class];
});
GREYAssert(shown, @"QLPreviewController was not shown.");
}
- (void)testDownloadUnauthorized {
if (!download::IsUsdzPreviewEnabled()) {
EARL_GREY_TEST_SKIPPED(
@"Disabled if 'USDZPreview' feature is disabled or on iOS versions "
"below 12 because QLPreviewController is not available.");
}
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGrey waitForWebViewContainingText:"Unauthorized"];
[ChromeEarlGrey tapWebViewElementWithID:@"unauthorized"];
// QLPreviewController UI is rendered out of host process so EarlGrey matcher
// can not find QLPreviewController UI. Instead this test relies on view
// controller presentation as the signal that QLPreviewController UI is shown.
UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
bool shown = WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^{
UIViewController* presentedController = BVC.presentedViewController;
return [presentedController class] == [QLPreviewController class];
});
GREYAssertFalse(shown, @"QLPreviewController should not have shown.");
}
- (void)testDownloadForbidden {
if (!download::IsUsdzPreviewEnabled()) {
EARL_GREY_TEST_SKIPPED(
@"Disabled if 'USDZPreview' feature is disabled or on iOS versions "
"below 12 because QLPreviewController is not available.");
}
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGrey waitForWebViewContainingText:"Forbidden"];
[ChromeEarlGrey tapWebViewElementWithID:@"forbidden"];
// QLPreviewController UI is rendered out of host process so EarlGrey matcher
// can not find QLPreviewController UI. Instead this test relies on view
// controller presentation as the signal that QLPreviewController UI is shown.
UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
bool shown = WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^{
UIViewController* presentedController = BVC.presentedViewController;
return [presentedController class] == [QLPreviewController class];
});
GREYAssertFalse(shown, @"QLPreviewController should not have shown.");
}
- (void)testDownloadChangingMimeType {
if (!download::IsUsdzPreviewEnabled()) {
EARL_GREY_TEST_SKIPPED(
@"Disabled if 'USDZPreview' feature is disabled or on iOS versions "
"below 12 because QLPreviewController is not available.");
}
[ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
[ChromeEarlGrey waitForWebViewContainingText:"Changing Mime Type"];
[ChromeEarlGrey tapWebViewElementWithID:@"changing-mime-type"];
// QLPreviewController UI is rendered out of host process so EarlGrey matcher
// can not find QLPreviewController UI. Instead this test relies on view
// controller presentation as the signal that QLPreviewController UI is shown.
UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
bool shown = WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^{
UIViewController* presentedController = BVC.presentedViewController;
return [presentedController class] == [QLPreviewController class];
});
GREYAssertFalse(shown, @"QLPreviewController should not have shown.");
}
@end
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/histogram_tester.h"
#include "components/infobars/core/confirm_infobar_delegate.h" #include "components/infobars/core/confirm_infobar_delegate.h"
#include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar.h"
#include "ios/chrome/browser/download/download_test_util.h"
#import "ios/chrome/browser/download/pass_kit_tab_helper.h" #import "ios/chrome/browser/download/pass_kit_tab_helper.h"
#include "ios/chrome/browser/download/pass_kit_test_util.h"
#include "ios/chrome/browser/infobars/infobar_manager_impl.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
#include "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/browser/ui/util/ui_util.h"
#include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_strings.h"
...@@ -65,7 +65,7 @@ class PassKitCoordinatorTest : public PlatformTest { ...@@ -65,7 +65,7 @@ class PassKitCoordinatorTest : public PlatformTest {
// valid PKPass object. // valid PKPass object.
// TODO(crbug.com/804250): this test is flaky. // TODO(crbug.com/804250): this test is flaky.
TEST_F(PassKitCoordinatorTest, ValidPassKitObject) { TEST_F(PassKitCoordinatorTest, ValidPassKitObject) {
std::string data = testing::GetTestPass(); std::string data = testing::GetTestFileContents(testing::kPkPassFilePath);
NSData* nsdata = [NSData dataWithBytes:data.c_str() length:data.size()]; NSData* nsdata = [NSData dataWithBytes:data.c_str() length:data.size()];
PKPass* pass = [[PKPass alloc] initWithData:nsdata error:nil]; PKPass* pass = [[PKPass alloc] initWithData:nsdata error:nil];
ASSERT_TRUE(pass); ASSERT_TRUE(pass);
...@@ -107,7 +107,7 @@ TEST_F(PassKitCoordinatorTest, MultiplePassKitObjects) { ...@@ -107,7 +107,7 @@ TEST_F(PassKitCoordinatorTest, MultiplePassKitObjects) {
return; return;
} }
std::string data = testing::GetTestPass(); std::string data = testing::GetTestFileContents(testing::kPkPassFilePath);
NSData* nsdata = [NSData dataWithBytes:data.c_str() length:data.size()]; NSData* nsdata = [NSData dataWithBytes:data.c_str() length:data.size()];
PKPass* pass = [[PKPass alloc] initWithData:nsdata error:nil]; PKPass* pass = [[PKPass alloc] initWithData:nsdata error:nil];
ASSERT_TRUE(pass); ASSERT_TRUE(pass);
...@@ -173,7 +173,7 @@ TEST_F(PassKitCoordinatorTest, AnotherViewControllerIsPresented) { ...@@ -173,7 +173,7 @@ TEST_F(PassKitCoordinatorTest, AnotherViewControllerIsPresented) {
})); }));
// Attempt to present "Add pkpass UI". // Attempt to present "Add pkpass UI".
std::string data = testing::GetTestPass(); std::string data = testing::GetTestFileContents(testing::kPkPassFilePath);
NSData* nsdata = [NSData dataWithBytes:data.c_str() length:data.size()]; NSData* nsdata = [NSData dataWithBytes:data.c_str() length:data.size()];
PKPass* pass = [[PKPass alloc] initWithData:nsdata error:nil]; PKPass* pass = [[PKPass alloc] initWithData:nsdata error:nil];
ASSERT_TRUE(pass); ASSERT_TRUE(pass);
......
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
#import "base/test/ios/wait_util.h" #import "base/test/ios/wait_util.h"
#import "ios/chrome/app/main_controller.h" #import "ios/chrome/app/main_controller.h"
#include "ios/chrome/browser/download/download_test_util.h"
#include "ios/chrome/browser/download/pass_kit_mime_type.h" #include "ios/chrome/browser/download/pass_kit_mime_type.h"
#include "ios/chrome/browser/download/pass_kit_test_util.h"
#import "ios/chrome/browser/ui/browser_view_controller.h" #import "ios/chrome/browser/ui/browser_view_controller.h"
#include "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/browser/ui/util/ui_util.h"
#include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_strings.h"
...@@ -53,7 +53,7 @@ std::unique_ptr<net::test_server::HttpResponse> GetResponse( ...@@ -53,7 +53,7 @@ std::unique_ptr<net::test_server::HttpResponse> GetResponse(
result->set_content("corrupted"); result->set_content("corrupted");
} else if (request.GetURL().path() == "/good") { } else if (request.GetURL().path() == "/good") {
result->AddCustomHeader("Content-Type", kPkPassMimeType); result->AddCustomHeader("Content-Type", kPkPassMimeType);
result->set_content(testing::GetTestPass()); result->set_content(testing::GetTestFileContents(testing::kPkPassFilePath));
} }
return result; return result;
......
...@@ -25,6 +25,7 @@ source_set("main") { ...@@ -25,6 +25,7 @@ source_set("main") {
"//ios/chrome/browser/crash_report:crash_report_internal", "//ios/chrome/browser/crash_report:crash_report_internal",
"//ios/chrome/browser/device_sharing", "//ios/chrome/browser/device_sharing",
"//ios/chrome/browser/download", "//ios/chrome/browser/download",
"//ios/chrome/browser/download:features",
"//ios/chrome/browser/sessions", "//ios/chrome/browser/sessions",
"//ios/chrome/browser/sessions:serialisation", "//ios/chrome/browser/sessions:serialisation",
"//ios/chrome/browser/store_kit", "//ios/chrome/browser/store_kit",
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#import "ios/chrome/browser/app_launcher/app_launcher_abuse_detector.h" #import "ios/chrome/browser/app_launcher/app_launcher_abuse_detector.h"
#import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h" #import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/download/ar_quick_look_tab_helper.h"
#import "ios/chrome/browser/download/features.h"
#import "ios/chrome/browser/download/pass_kit_tab_helper.h" #import "ios/chrome/browser/download/pass_kit_tab_helper.h"
#import "ios/chrome/browser/store_kit/store_kit_coordinator.h" #import "ios/chrome/browser/store_kit/store_kit_coordinator.h"
#import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h"
...@@ -23,6 +25,7 @@ ...@@ -23,6 +25,7 @@
#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h" #import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/download/ar_quick_look_coordinator.h"
#import "ios/chrome/browser/ui/download/pass_kit_coordinator.h" #import "ios/chrome/browser/ui/download/pass_kit_coordinator.h"
#import "ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h" #import "ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h"
#import "ios/chrome/browser/ui/print/print_controller.h" #import "ios/chrome/browser/ui/print/print_controller.h"
...@@ -62,6 +65,9 @@ ...@@ -62,6 +65,9 @@
// Coordinator for Page Info UI. // Coordinator for Page Info UI.
@property(nonatomic, strong) PageInfoLegacyCoordinator* pageInfoCoordinator; @property(nonatomic, strong) PageInfoLegacyCoordinator* pageInfoCoordinator;
// Coordinator to present a QLPreviewController for AR models.
@property(nonatomic, strong) ARQuickLookCoordinator* ARQuickLookCoordinator;
// Coordinator for the PassKit UI presentation. // Coordinator for the PassKit UI presentation.
@property(nonatomic, strong) PassKitCoordinator* passKitCoordinator; @property(nonatomic, strong) PassKitCoordinator* passKitCoordinator;
...@@ -182,6 +188,11 @@ ...@@ -182,6 +188,11 @@
self.pageInfoCoordinator.presentationProvider = self.viewController; self.pageInfoCoordinator.presentationProvider = self.viewController;
self.pageInfoCoordinator.tabModel = self.tabModel; self.pageInfoCoordinator.tabModel = self.tabModel;
if (download::IsUsdzPreviewEnabled()) {
self.ARQuickLookCoordinator = [[ARQuickLookCoordinator alloc]
initWithBaseViewController:self.viewController];
}
self.passKitCoordinator = [[PassKitCoordinator alloc] self.passKitCoordinator = [[PassKitCoordinator alloc]
initWithBaseViewController:self.viewController]; initWithBaseViewController:self.viewController];
...@@ -389,6 +400,11 @@ ...@@ -389,6 +400,11 @@
webState, [[AppLauncherAbuseDetector alloc] init], webState, [[AppLauncherAbuseDetector alloc] init],
self.appLauncherCoordinator); self.appLauncherCoordinator);
if (download::IsUsdzPreviewEnabled()) {
ARQuickLookTabHelper::CreateForWebState(webState,
self.ARQuickLookCoordinator);
}
PassKitTabHelper::CreateForWebState(webState, self.passKitCoordinator); PassKitTabHelper::CreateForWebState(webState, self.passKitCoordinator);
RepostFormTabHelper::CreateForWebState(webState, self); RepostFormTabHelper::CreateForWebState(webState, self);
......
...@@ -86,8 +86,8 @@ bundle_data("http_server_bundle_data") { ...@@ -86,8 +86,8 @@ bundle_data("http_server_bundle_data") {
"data/http_server_files/onload_replacestate_reload.js", "data/http_server_files/onload_replacestate_reload.js",
"data/http_server_files/opensearch.xml", "data/http_server_files/opensearch.xml",
"data/http_server_files/pony.html", "data/http_server_files/pony.html",
"data/http_server_files/redchair.usdz",
"data/http_server_files/redirect_refresh.html", "data/http_server_files/redirect_refresh.html",
"data/http_server_files/retrotv.usdz",
"data/http_server_files/single_page_wide.pdf", "data/http_server_files/single_page_wide.pdf",
"data/http_server_files/state_operations.html", "data/http_server_files/state_operations.html",
"data/http_server_files/state_operations.js", "data/http_server_files/state_operations.js",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment