Commit 745d926a authored by Peter K. Lee's avatar Peter K. Lee Committed by Commit Bot

Handle classes/externs that are not available on iOS 10.0

UI*FeedbackGenerator and AVCaptureDevice* classes are claimed to be
available for iOS 10+, but they are not really available at runtime on
iOS 10.0. iOS 10.1+ appears to be OK. Use workarounds for unavailable
symbols.

Bug: 824941
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: Idb9e42e6f72cbd96ff81e99f3ec455c03e09f8ce
Reviewed-on: https://chromium-review.googlesource.com/976945
Commit-Queue: Peter Lee <pkl@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#546240}
parent 1cc3eead
...@@ -52,6 +52,19 @@ source_set("coordinator") { ...@@ -52,6 +52,19 @@ source_set("coordinator") {
] ]
} }
source_set("unit_tests") {
configs += [ "//build/config/compiler:enable_arc" ]
testonly = true
sources = [
"camera_controller_unittest.mm",
]
deps = [
":qr_scanner",
"//base",
"//testing/gtest:gtest",
]
}
source_set("eg_tests") { source_set("eg_tests") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
testonly = true testonly = true
......
...@@ -183,14 +183,27 @@ ...@@ -183,14 +183,27 @@
// Get the back camera. // Get the back camera.
NSArray* videoCaptureDevices = nil; NSArray* videoCaptureDevices = nil;
if (@available(iOS 10, *)) { if (@available(iOS 10, *)) {
AVCaptureDeviceDiscoverySession* discoverySession = // Although Apple documentation claims that
[AVCaptureDeviceDiscoverySession // AVCaptureDeviceDiscoverySession etc. is available on iOS 10+, they are
discoverySessionWithDeviceTypes:@[ // not really available on an app whose deployment target is iOS 10.0
AVCaptureDeviceTypeBuiltInWideAngleCamera // (iOS 10.1+ are okay) and Chrome will fail at dynamic link time and
] // instantly crash. NSClassFromString() checks if Objective-C run-time
mediaType:AVMediaTypeVideo // has the classes before using them.
position:AVCaptureDevicePositionBack]; Class discoverSessionClass =
videoCaptureDevices = [discoverySession devices]; NSClassFromString(@"AVCaptureDeviceDiscoverySession");
if (discoverSessionClass) {
// Hardcoded value of AVCaptureDeviceTypeBuiltInWideAngleCamera here.
// When this @available(iOS 10, *) is deprecated, the unit test
// CameraControllerTest.TestAVCaptureDeviceValue can be removed.
// See https://crbug.com/826011
NSString* cameraType = @"AVCaptureDeviceTypeBuiltInWideAngleCamera";
AVCaptureDeviceDiscoverySession* discoverySession =
[discoverSessionClass
discoverySessionWithDeviceTypes:@[ cameraType ]
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionBack];
videoCaptureDevices = [discoverySession devices];
}
} }
#if !defined(__IPHONE_10_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0 #if !defined(__IPHONE_10_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
else { else {
......
// 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 "ios/chrome/browser/ui/qr_scanner/camera_controller.h"
#include "testing/gtest_mac.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using CameraControllerTest = PlatformTest;
TEST_F(CameraControllerTest, TestAVCaptureDeviceValue) {
// Although Apple documentation claims that AVCaptureDeviceDiscoverySession
// etc. is available on iOS 10+, they are not really available on an app
// whose deployment target is iOS 10.0 (iOS 10.1+ are okay) and Chrome will
// fail at dynamic link time and instantly crash. To make this work, the
// actual value for the global variable
// |AVCaptureDeviceTypeBuiltInWideAngleCamera| is used literally in
// camera_controller.mm. This unit test detects if a newer iOS version
// changes this value. If this unit test fails, check the implementation
// of -loadCaptureSession: in camera_controller.mm.
//
// The following use of AVCaptureDeviceTypeBuiltInWideAngleCamera
// will cause unit tests to be not runnable on iOS 10.0 devices due to
// failure at dynamic link (dyld) time.
// TODO(crbug.com/826011): Remove this when iOS 10.0 support is deprecated.
EXPECT_NSEQ(AVCaptureDeviceTypeBuiltInWideAngleCamera,
@"AVCaptureDeviceTypeBuiltInWideAngleCamera");
}
...@@ -581,9 +581,17 @@ UIResponder* GetFirstResponder() { ...@@ -581,9 +581,17 @@ UIResponder* GetFirstResponder() {
// action. This is a no-op for devices that do not support it. // action. This is a no-op for devices that do not support it.
void TriggerHapticFeedbackForAction() { void TriggerHapticFeedbackForAction() {
if (@available(iOS 10, *)) { if (@available(iOS 10, *)) {
UIImpactFeedbackGenerator* generator = // Although Apple documentation claims that UIFeedbackGenerator and its
[[UIImpactFeedbackGenerator alloc] init]; // concrete subclasses are available on iOS 10+, they are not really
[generator impactOccurred]; // available on an app whose deployment target is iOS 10.0 (iOS 10.1+ are
// okay) and Chrome will fail at dynamic link time and instantly crash.
// NSClassFromString() checks if Objective-C run-time has the class before
// using it.
Class generatorClass = NSClassFromString(@"UIImpactFeedbackGenerator");
if (generatorClass) {
UIImpactFeedbackGenerator* generator = [[generatorClass alloc] init];
[generator impactOccurred];
}
} }
} }
...@@ -591,9 +599,17 @@ void TriggerHapticFeedbackForAction() { ...@@ -591,9 +599,17 @@ void TriggerHapticFeedbackForAction() {
// This is a no-op for devices that do not support it. // This is a no-op for devices that do not support it.
void TriggerHapticFeedbackForSelectionChange() { void TriggerHapticFeedbackForSelectionChange() {
if (@available(iOS 10, *)) { if (@available(iOS 10, *)) {
UISelectionFeedbackGenerator* generator = // Although Apple documentation claims that UIFeedbackGenerator and its
[[UISelectionFeedbackGenerator alloc] init]; // concrete subclasses are available on iOS 10+, they are not really
[generator selectionChanged]; // available on an app whose deployment target is iOS 10.0 (iOS 10.1+ are
// okay) and Chrome will fail at dynamic link time and instantly crash.
// NSClassFromString() checks if Objective-C run-time has the class before
// using it.
Class generatorClass = NSClassFromString(@"UISelectionFeedbackGenerator");
if (generatorClass) {
UISelectionFeedbackGenerator* generator = [[generatorClass alloc] init];
[generator selectionChanged];
}
} }
} }
...@@ -601,9 +617,19 @@ void TriggerHapticFeedbackForSelectionChange() { ...@@ -601,9 +617,19 @@ void TriggerHapticFeedbackForSelectionChange() {
// This is a no-op for devices that do not support it. // This is a no-op for devices that do not support it.
void TriggerHapticFeedbackForNotification(UINotificationFeedbackType type) { void TriggerHapticFeedbackForNotification(UINotificationFeedbackType type) {
if (@available(iOS 10, *)) { if (@available(iOS 10, *)) {
UINotificationFeedbackGenerator* generator = // Although Apple documentation claims that UIFeedbackGenerator and its
[[UINotificationFeedbackGenerator alloc] init]; // concrete subclasses are available on iOS 10+, they are not really
[generator notificationOccurred:type]; // available on an app whose deployment target is iOS 10.0 (iOS 10.1+ are
// okay) and Chrome will fail at dynamic link time and instantly crash.
// NSClassFromString() checks if Objective-C run-time has the class before
// using it.
Class generatorClass =
NSClassFromString(@"UINotificationFeedbackGenerator");
if (generatorClass) {
UINotificationFeedbackGenerator* generator =
[[generatorClass alloc] init];
[generator notificationOccurred:type];
}
} }
} }
......
...@@ -213,6 +213,7 @@ test("ios_chrome_unittests") { ...@@ -213,6 +213,7 @@ test("ios_chrome_unittests") {
"//ios/chrome/browser/ui/popup_menu:unit_tests", "//ios/chrome/browser/ui/popup_menu:unit_tests",
"//ios/chrome/browser/ui/presenters:unit_tests", "//ios/chrome/browser/ui/presenters:unit_tests",
"//ios/chrome/browser/ui/promos:unit_tests", "//ios/chrome/browser/ui/promos:unit_tests",
"//ios/chrome/browser/ui/qr_scanner:unit_tests",
"//ios/chrome/browser/ui/reading_list:unit_tests", "//ios/chrome/browser/ui/reading_list:unit_tests",
"//ios/chrome/browser/ui/safe_mode:unit_tests", "//ios/chrome/browser/ui/safe_mode:unit_tests",
"//ios/chrome/browser/ui/settings:unit_tests", "//ios/chrome/browser/ui/settings:unit_tests",
......
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