Commit 05bc8d81 authored by Hiroshi Ichikawa's avatar Hiroshi Ichikawa Committed by Commit Bot

Simplify CRWWebViewScrollViewProxy implementation.

Simplify based on the fact that we can now assume that
self.underlyingScrollView is never nil.

Especially, simplify the properties preservation by deleting
CRWPropertiesStore and simply assigning them from the old scroll view to the
new scroll view.

Bug: 1023250
Change-Id: I29e97ff154a92b1ec0ad9ea91d27bc7a393f4ecf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2132892
Auto-Submit: Hiroshi Ichikawa <ichikawa@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Commit-Queue: Hiroshi Ichikawa <ichikawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756560}
parent c4c43642
......@@ -485,7 +485,6 @@ source_set("ios_web_web_state_ui_unittests") {
]
sources = [
"web_state/ui/crw_properties_store_unittest.mm",
"web_state/ui/crw_web_controller_unittest.mm",
"web_state/ui/crw_web_view_content_view_unittest.mm",
"web_state/ui/crw_web_view_proxy_impl_unittest.mm",
......
......@@ -47,8 +47,6 @@ source_set("ui") {
]
sources = [
"crw_properties_store.h",
"crw_properties_store.mm",
"crw_swipe_recognizer_provider.h",
"crw_touch_tracking_recognizer.h",
"crw_touch_tracking_recognizer.mm",
......
// Copyright 2019 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_WEB_WEB_STATE_UI_CRW_PROPERTIES_STORE_H_
#define IOS_WEB_WEB_STATE_UI_CRW_PROPERTIES_STORE_H_
#import <Foundation/Foundation.h>
// An attribute of a property with an Objective-C object type to be preserved.
typedef NS_ENUM(NSInteger, CRWStoredPropertyAttribute) {
// "strong" attribute.
CRWStoredPropertyAttributeStrong,
// "weak" attribute.
CRWStoredPropertyAttributeWeak,
// "copy" attribute.
CRWStoredPropertyAttributeCopy,
};
// An object which preserves properties of an underlying object when the
// underlying object is reassigned.
//
// This is useful when:
// - A class is a proxy for an underlying object.
// - The underlying object can be nil or reassigned during the lifetime of the
// wrapper.
// - The proxy should preserve a subset of the properties of the underlying
// object when the underlying object is reassigned.
//
// A caller must call its "register" methods to register properties to be
// preserved before using it.
//
// TODO(crbug.com/1023250): Add a unit test for this class.
// TODO(crbug.com/1023250): Add more safety checks for this class.
@interface CRWPropertiesStore : NSObject
// Registers a property with an Objective-C object type to be preserved.
// |getter| and |setter| are selectors of the getter/setter of the underlying
// object.
- (void)registerObjectPropertyWithGetter:(nonnull SEL)getter
setter:(nonnull SEL)setter
attribute:(CRWStoredPropertyAttribute)attribute;
// Registers a property with a type not an Objective-C object to be preserved.
// |getter| and |setter| are selectors of the getter/setter of the underlying
// object. |type| is the type encoding of the property type e.g., @encode(BOOL).
//
// This should be used e.g., for scalar types (NSInteger, CGFloat, etc.) and C
// structures (CGRect, CGPoint, etc.).
- (void)registerNonObjectPropertyWithGetter:(nonnull SEL)getter
setter:(nonnull SEL)setter
type:(nonnull const char*)type;
// Saves the properties of |object| to the properties store. Should be called
// against the old underlying object when the underlying object is reassigned.
- (void)savePropertiesFromObject:(nonnull id)object;
// Loads the properties from the properties store to |object|. Should be called
// against the new underlying object when the underlying object is reassigned.
- (void)loadPropertiesToObject:(nonnull id)object;
// Clears values of all the properties in the properties store. This prevents
// from retaining property values no longer needed. It does not reset
// registration of properties.
- (void)clearValues;
// Forwards |invocation| to the properties store.
//
// If |invocation| is an invocation of a getter or setter of a registered
// property, it gets or sets the property in the property store, which is later
// restored in the underlying object, and returns YES. Otherwise does nothing
// and returns NO.
//
// This should be called in -forwardInvocation: of the wrapper when the
// underlying object is nil.
- (BOOL)forwardInvocationToPropertiesStore:(nonnull NSInvocation*)invocation;
@end
#endif // IOS_WEB_WEB_STATE_UI_CRW_PROPERTIES_STORE_H_
This diff is collapsed.
// Copyright 2020 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/web/web_state/ui/crw_properties_store.h"
#import <Foundation/Foundation.h>
#include "base/compiler_specific.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
// A protocol with properties used for the test.
@protocol CRWTestProtocol <NSObject>
@property(nonatomic) NSInteger nonObjectProperty;
@property(nonatomic, strong) NSObject* strongProperty;
@property(nonatomic, weak) NSObject* weakProperty;
@property(nonatomic, copy) NSObject* copiedProperty;
@end
// An object with properties used for the test.
@interface CRWTestObject : NSObject <CRWTestProtocol>
@end
@implementation CRWTestObject
@synthesize nonObjectProperty = _nonObjectProperty;
@synthesize strongProperty = _strongProperty;
@synthesize weakProperty = _weakProperty;
@synthesize copiedProperty = _copiedProperty;
@end
// An object which forwards all invocations to a CRWPropertiesStore.
@interface CRWTestProxy : NSObject
@property(nonatomic) CRWPropertiesStore* propertiesStore;
@end
// Conform to the protocol in a category, which allows to conform to a protocol
// without implementing the properties explicitly.
@interface CRWTestProxy (CRWTestProtocol) <CRWTestProtocol>
@end
@implementation CRWTestProxy
- (NSMethodSignature*)methodSignatureForSelector:(SEL)sel {
return [CRWTestObject instanceMethodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation*)invocation {
[_propertiesStore forwardInvocationToPropertiesStore:invocation];
}
@end
class CRWPropertiesStoreTest : public PlatformTest {
public:
CRWPropertiesStoreTest()
: properties_store_([[CRWPropertiesStore alloc] init]),
proxy_([[CRWTestProxy alloc] init]) {
[properties_store_
registerNonObjectPropertyWithGetter:@selector(nonObjectProperty)
setter:@selector(setNonObjectProperty:)
type:@encode(NSInteger)];
[properties_store_
registerObjectPropertyWithGetter:@selector(strongProperty)
setter:@selector(setStrongProperty:)
attribute:CRWStoredPropertyAttributeStrong];
[properties_store_
registerObjectPropertyWithGetter:@selector(weakProperty)
setter:@selector(setWeakProperty:)
attribute:CRWStoredPropertyAttributeWeak];
[properties_store_
registerObjectPropertyWithGetter:@selector(copiedProperty)
setter:@selector(setCopiedProperty:)
attribute:CRWStoredPropertyAttributeCopy];
proxy_.propertiesStore = properties_store_;
}
protected:
CRWPropertiesStore* properties_store_;
CRWTestProxy* proxy_;
};
// Tests that a value of an non-object type property is preserved when accessed
// via -forwardInvocationToPropertiesStore:.
TEST_F(CRWPropertiesStoreTest, PreserveForwardedNonObjectProperty) {
EXPECT_EQ(0, proxy_.nonObjectProperty);
proxy_.nonObjectProperty = 1;
EXPECT_EQ(1, proxy_.nonObjectProperty);
}
// Tests that a value of a strong property is preserved when accessed via
// -forwardInvocationToPropertiesStore:.
TEST_F(CRWPropertiesStoreTest, PreserveForwardedStrongProperty) {
NSObject* strong_value = [[NSObject alloc] init];
__weak NSObject* weak_value = strong_value;
EXPECT_FALSE(proxy_.strongProperty);
proxy_.strongProperty = strong_value;
EXPECT_EQ(strong_value, proxy_.strongProperty);
// Verify that the object is retained by CRWPropertiesStore.
strong_value = nil;
EXPECT_EQ(weak_value, proxy_.strongProperty);
}
// Tests that a value of a weak property is preserved when accessed via
// -forwardInvocationToPropertiesStore:.
TEST_F(CRWPropertiesStoreTest, PreserveForwardedWeakProperty) {
NSObject* strong_value = [[NSObject alloc] init];
EXPECT_FALSE(proxy_.weakProperty);
proxy_.weakProperty = strong_value;
EXPECT_EQ(strong_value, proxy_.weakProperty);
// Verify that the object is NOT retained by CRWPropertiesStore.
strong_value = nil;
EXPECT_FALSE(proxy_.weakProperty);
}
// Tests that a value of a copy property is preserved when accessed via
// -forwardInvocationToPropertiesStore:.
TEST_F(CRWPropertiesStoreTest, PreserveForwardedCopiedProperty) {
// Use an NSMutableString as an example object here so that its -copy returns
// a different object from itself. -[NSString copy] may return itself.
NSMutableString* string = [@"hoge" mutableCopy];
EXPECT_FALSE(proxy_.copiedProperty);
proxy_.copiedProperty = string;
// Verify that it is copied i.e., it -isEqual: to the original object but not
// the same instance.
EXPECT_NSEQ(string, proxy_.copiedProperty);
EXPECT_NE(string, proxy_.copiedProperty);
}
// Tests that -savePropertiesFromObject: works as expected.
TEST_F(CRWPropertiesStoreTest, SaveProperties) {
NSObject* object_value1 = [[NSObject alloc] init];
NSObject* object_value2 = [[NSObject alloc] init];
NSMutableString* copyable_value = [@"hoge" mutableCopy];
CRWTestObject* object = [[CRWTestObject alloc] init];
object.nonObjectProperty = 1;
object.strongProperty = object_value1;
object.weakProperty = object_value2;
object.copiedProperty = copyable_value;
[properties_store_ savePropertiesFromObject:object];
EXPECT_EQ(1, proxy_.nonObjectProperty);
EXPECT_EQ(object_value1, proxy_.strongProperty);
EXPECT_EQ(object_value2, proxy_.weakProperty);
EXPECT_NSEQ(copyable_value, proxy_.copiedProperty);
}
// Tests that -loadPropertiesToObject: works as expected.
TEST_F(CRWPropertiesStoreTest, LoadProperties) {
NSObject* object_value1 = [[NSObject alloc] init];
NSObject* object_value2 = [[NSObject alloc] init];
NSMutableString* copyable_value = [@"hoge" mutableCopy];
proxy_.nonObjectProperty = 1;
proxy_.strongProperty = object_value1;
proxy_.weakProperty = object_value2;
proxy_.copiedProperty = copyable_value;
CRWTestObject* object = [[CRWTestObject alloc] init];
[properties_store_ loadPropertiesToObject:object];
EXPECT_EQ(1, object.nonObjectProperty);
EXPECT_EQ(object_value1, object.strongProperty);
EXPECT_EQ(object_value2, object.weakProperty);
EXPECT_NSEQ(copyable_value, object.copiedProperty);
}
// Tests that -clearValues works as expected.
TEST_F(CRWPropertiesStoreTest, ClearValues) {
NSObject* object_value1 = [[NSObject alloc] init];
NSObject* object_value2 = [[NSObject alloc] init];
NSMutableString* copyable_value = [@"hoge" mutableCopy];
proxy_.nonObjectProperty = 1;
proxy_.strongProperty = object_value1;
proxy_.weakProperty = object_value2;
proxy_.copiedProperty = copyable_value;
[properties_store_ clearValues];
EXPECT_EQ(0, proxy_.nonObjectProperty);
EXPECT_FALSE(proxy_.strongProperty);
EXPECT_FALSE(proxy_.weakProperty);
EXPECT_FALSE(proxy_.copiedProperty);
}
......@@ -590,7 +590,7 @@ TEST_F(CRWWebViewScrollViewProxyTest, RemoveKVObserver) {
// - the setter is called when the underlying scroll view is not set
// - the getter is called after the underlying scroll view is still not set
TEST_F(CRWWebViewScrollViewProxyTest,
PreservePropertiesWhileUnderlyingScrollViewIsNil) {
PreservePropertiesWhileUnderlyingScrollViewIsAbsent) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
web::features::kPreserveScrollViewProperties);
......
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