diff options
author | tapted@chromium.org <tapted@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-12 12:03:48 +0000 |
---|---|---|
committer | tapted@chromium.org <tapted@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-12 12:05:27 +0000 |
commit | 0b7f85234f13b9e644cb63be4b560a26e0c09c2e (patch) | |
tree | f2e0695554513feb1c32f1d9410c59b8bc97da72 | |
parent | 5f01d48039db9d83409290e3f2ebd5c159e97a9e (diff) | |
download | chromium_src-0b7f85234f13b9e644cb63be4b560a26e0c09c2e.zip chromium_src-0b7f85234f13b9e644cb63be4b560a26e0c09c2e.tar.gz chromium_src-0b7f85234f13b9e644cb63be4b560a26e0c09c2e.tar.bz2 |
Add ScopedObjCClassSwizzler in base/mac, absorbs objc_method_swizzle and ScopedClassSwizzler
ScopedClassSwizzler from ui/test is wanted for new tests where it can't
currently be accessed. It also re-implements a concept in
chrome/common/mac/objc_method_swizzle.*
This change adds base::mac::ScopedObjCClassSwizzler, merges concepts
from objc_method_swizzle, and adjusts chrome_browser_application_mac.mm
to use the new swizzler.
The test from objc_method_swizzle is adapted and extended for the scoped
swizzler.
BUG=378134
TEST=base_unittests
Review URL: https://codereview.chromium.org/345243007
Cr-Commit-Position: refs/heads/master@{#288943}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288943 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/BUILD.gn | 3 | ||||
-rw-r--r-- | base/base.gyp | 1 | ||||
-rw-r--r-- | base/base.gypi | 2 | ||||
-rw-r--r-- | base/mac/scoped_objc_class_swizzler.h | 49 | ||||
-rw-r--r-- | base/mac/scoped_objc_class_swizzler.mm | 71 | ||||
-rw-r--r-- | base/mac/scoped_objc_class_swizzler_unittest.mm | 166 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_application_mac.mm | 13 | ||||
-rw-r--r-- | chrome/chrome_common.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests_unit.gypi | 1 | ||||
-rw-r--r-- | chrome/common/mac/objc_method_swizzle.h | 27 | ||||
-rw-r--r-- | chrome/common/mac/objc_method_swizzle.mm | 57 | ||||
-rw-r--r-- | chrome/common/mac/objc_method_swizzle_unittest.mm | 76 | ||||
-rw-r--r-- | chrome/common/mac/objc_zombie.mm | 1 | ||||
-rw-r--r-- | ui/base/cocoa/cocoa_base_utils_unittest.mm | 5 | ||||
-rw-r--r-- | ui/events/cocoa/events_mac_unittest.mm | 13 | ||||
-rw-r--r-- | ui/events/test/cocoa_test_event_utils.h | 14 | ||||
-rw-r--r-- | ui/events/test/cocoa_test_event_utils.mm | 16 | ||||
-rw-r--r-- | ui/views/test/event_generator_delegate_mac.mm | 6 |
18 files changed, 312 insertions, 211 deletions
diff --git a/base/BUILD.gn b/base/BUILD.gn index 3c0597b..7954972 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -300,6 +300,8 @@ component("base") { "mac/scoped_nsexception_enabler.h", "mac/scoped_nsexception_enabler.mm", "mac/scoped_nsobject.h", + "mac/scoped_objc_class_swizzler.h", + "mac/scoped_objc_class_swizzler.mm", "mac/scoped_sending_event.h", "mac/scoped_sending_event.mm", "mac/sdk_forward_declarations.h", @@ -1121,6 +1123,7 @@ test("base_unittests") { "mac/mac_util_unittest.mm", "mac/objc_property_releaser_unittest.mm", "mac/scoped_nsobject_unittest.mm", + "mac/scoped_objc_class_swizzler_unittest.mm", "mac/scoped_sending_event_unittest.mm", "md5_unittest.cc", "memory/aligned_memory_unittest.cc", diff --git a/base/base.gyp b/base/base.gyp index 2eaa614..9c0c203 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -496,6 +496,7 @@ 'mac/mac_util_unittest.mm', 'mac/objc_property_releaser_unittest.mm', 'mac/scoped_nsobject_unittest.mm', + 'mac/scoped_objc_class_swizzler_unittest.mm', 'mac/scoped_sending_event_unittest.mm', 'md5_unittest.cc', 'memory/aligned_memory_unittest.cc', diff --git a/base/base.gypi b/base/base.gypi index 7560e8f..fd64aef 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -304,6 +304,8 @@ 'mac/scoped_nsexception_enabler.h', 'mac/scoped_nsexception_enabler.mm', 'mac/scoped_nsobject.h', + 'mac/scoped_objc_class_swizzler.h', + 'mac/scoped_objc_class_swizzler.mm', 'mac/scoped_sending_event.h', 'mac/scoped_sending_event.mm', 'mac/scoped_typeref.h', diff --git a/base/mac/scoped_objc_class_swizzler.h b/base/mac/scoped_objc_class_swizzler.h new file mode 100644 index 0000000..e18e4ab --- /dev/null +++ b/base/mac/scoped_objc_class_swizzler.h @@ -0,0 +1,49 @@ +// Copyright 2014 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 BASE_MAC_SCOPED_OBJC_CLASS_SWIZZLER_H_ +#define BASE_MAC_SCOPED_OBJC_CLASS_SWIZZLER_H_ + +#import <objc/runtime.h> + +#include "base/base_export.h" +#include "base/macros.h" + +namespace base { +namespace mac { + +// Within a given scope, swaps method implementations of a class interface, or +// between two class interfaces. The argument and return types must match. +class BASE_EXPORT ScopedObjCClassSwizzler { + public: + // Given two classes that each respond to |selector|, swap the implementations + // of those methods. + ScopedObjCClassSwizzler(Class target, Class source, SEL selector); + + // Given two selectors on the same class interface, |target| (e.g. via + // inheritance or categories), swap the implementations of methods |original| + // and |alternate|. + ScopedObjCClassSwizzler(Class target, SEL original, SEL alternate); + + ~ScopedObjCClassSwizzler(); + + // Return a callable function pointer for the replaced method. To call this + // from the replacing function, the first two arguments should be |self| and + // |_cmd|. These are followed by the (variadic) method arguments. + IMP GetOriginalImplementation(); + + private: + // Delegated constructor. + void Init(Class target, Class source, SEL original, SEL alternate); + + Method old_selector_impl_; + Method new_selector_impl_; + + DISALLOW_COPY_AND_ASSIGN(ScopedObjCClassSwizzler); +}; + +} // namespace mac +} // namespace base + +#endif // BASE_MAC_SCOPED_OBJC_CLASS_SWIZZLER_H_ diff --git a/base/mac/scoped_objc_class_swizzler.mm b/base/mac/scoped_objc_class_swizzler.mm new file mode 100644 index 0000000..20e5c56 --- /dev/null +++ b/base/mac/scoped_objc_class_swizzler.mm @@ -0,0 +1,71 @@ +// Copyright 2014 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 "base/mac/scoped_objc_class_swizzler.h" + +#include <string.h> + +#include "base/logging.h" + +namespace base { +namespace mac { + +ScopedObjCClassSwizzler::ScopedObjCClassSwizzler(Class target, + Class source, + SEL selector) + : old_selector_impl_(NULL), new_selector_impl_(NULL) { + Init(target, source, selector, selector); +} + +ScopedObjCClassSwizzler::ScopedObjCClassSwizzler(Class target, + SEL original, + SEL alternate) + : old_selector_impl_(NULL), new_selector_impl_(NULL) { + Init(target, target, original, alternate); +} + +ScopedObjCClassSwizzler::~ScopedObjCClassSwizzler() { + if (old_selector_impl_ && new_selector_impl_) + method_exchangeImplementations(old_selector_impl_, new_selector_impl_); +} + +IMP ScopedObjCClassSwizzler::GetOriginalImplementation() { + // Note that while the swizzle is in effect the "new" method is actually + // pointing to the original implementation, since they have been swapped. + return method_getImplementation(new_selector_impl_); +} + +void ScopedObjCClassSwizzler::Init(Class target, + Class source, + SEL original, + SEL alternate) { + old_selector_impl_ = class_getInstanceMethod(target, original); + new_selector_impl_ = class_getInstanceMethod(source, alternate); + if (!old_selector_impl_ && !new_selector_impl_) { + // Try class methods. + old_selector_impl_ = class_getClassMethod(target, original); + new_selector_impl_ = class_getClassMethod(source, alternate); + } + + DCHECK(old_selector_impl_); + DCHECK(new_selector_impl_); + if (!old_selector_impl_ || !new_selector_impl_) + return; + + // The argument and return types must match exactly. + const char* old_types = method_getTypeEncoding(old_selector_impl_); + const char* new_types = method_getTypeEncoding(new_selector_impl_); + DCHECK(old_types); + DCHECK(new_types); + DCHECK_EQ(0, strcmp(old_types, new_types)); + if (!old_types || !new_types || strcmp(old_types, new_types)) { + old_selector_impl_ = new_selector_impl_ = NULL; + return; + } + + method_exchangeImplementations(old_selector_impl_, new_selector_impl_); +} + +} // namespace mac +} // namespace base diff --git a/base/mac/scoped_objc_class_swizzler_unittest.mm b/base/mac/scoped_objc_class_swizzler_unittest.mm new file mode 100644 index 0000000..eacd105 --- /dev/null +++ b/base/mac/scoped_objc_class_swizzler_unittest.mm @@ -0,0 +1,166 @@ +// Copyright 2014 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 "base/mac/scoped_objc_class_swizzler.h" + +#import "base/mac/scoped_nsobject.h" +#include "testing/gtest/include/gtest/gtest.h" + +@interface ObjCClassSwizzlerTestOne : NSObject ++ (NSInteger)function; +- (NSInteger)method; +- (NSInteger)modifier; +@end + +@interface ObjCClassSwizzlerTestTwo : NSObject ++ (NSInteger)function; +- (NSInteger)method; +- (NSInteger)modifier; +@end + +@implementation ObjCClassSwizzlerTestOne : NSObject + ++ (NSInteger)function { + return 10; +} + +- (NSInteger)method { + // Multiply by a modifier to ensure |self| in a swizzled implementation + // refers to the original object. + return 1 * [self modifier]; +} + +- (NSInteger)modifier { + return 3; +} + +@end + +@implementation ObjCClassSwizzlerTestTwo : NSObject + ++ (NSInteger)function { + return 20; +} + +- (NSInteger)method { + return 2 * [self modifier]; +} + +- (NSInteger)modifier { + return 7; +} + +@end + +@interface ObjCClassSwizzlerTestOne (AlternateCategory) +- (NSInteger)alternate; +@end + +@implementation ObjCClassSwizzlerTestOne (AlternateCategory) +- (NSInteger)alternate { + return 3 * [self modifier]; +} +@end + +@interface ObjCClassSwizzlerTestOneChild : ObjCClassSwizzlerTestOne +- (NSInteger)childAlternate; +@end + +@implementation ObjCClassSwizzlerTestOneChild +- (NSInteger)childAlternate { + return 5 * [self modifier]; +} +@end + +namespace base { +namespace mac { + +TEST(ObjCClassSwizzlerTest, SwizzleInstanceMethods) { + base::scoped_nsobject<ObjCClassSwizzlerTestOne> object_one( + [[ObjCClassSwizzlerTestOne alloc] init]); + base::scoped_nsobject<ObjCClassSwizzlerTestTwo> object_two( + [[ObjCClassSwizzlerTestTwo alloc] init]); + EXPECT_EQ(3, [object_one method]); + EXPECT_EQ(14, [object_two method]); + + { + base::mac::ScopedObjCClassSwizzler swizzler( + [ObjCClassSwizzlerTestOne class], + [ObjCClassSwizzlerTestTwo class], + @selector(method)); + EXPECT_EQ(6, [object_one method]); + EXPECT_EQ(7, [object_two method]); + + IMP original = swizzler.GetOriginalImplementation(); + id expected_result = reinterpret_cast<id>(3); + EXPECT_EQ(expected_result, original(object_one, @selector(method))); + } + + EXPECT_EQ(3, [object_one method]); + EXPECT_EQ(14, [object_two method]); +} + +TEST(ObjCClassSwizzlerTest, SwizzleClassMethods) { + EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]); + EXPECT_EQ(20, [ObjCClassSwizzlerTestTwo function]); + + { + base::mac::ScopedObjCClassSwizzler swizzler( + [ObjCClassSwizzlerTestOne class], + [ObjCClassSwizzlerTestTwo class], + @selector(function)); + EXPECT_EQ(20, [ObjCClassSwizzlerTestOne function]); + EXPECT_EQ(10, [ObjCClassSwizzlerTestTwo function]); + + IMP original = swizzler.GetOriginalImplementation(); + id expected_result = reinterpret_cast<id>(10); + EXPECT_EQ(expected_result, original(nil, @selector(function))); + } + + EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]); + EXPECT_EQ(20, [ObjCClassSwizzlerTestTwo function]); +} + +TEST(ObjCClassSwizzlerTest, SwizzleViaCategory) { + base::scoped_nsobject<ObjCClassSwizzlerTestOne> object_one( + [[ObjCClassSwizzlerTestOne alloc] init]); + EXPECT_EQ(3, [object_one method]); + + { + base::mac::ScopedObjCClassSwizzler swizzler( + [ObjCClassSwizzlerTestOne class], + @selector(method), + @selector(alternate)); + EXPECT_EQ(9, [object_one method]); + + IMP original = swizzler.GetOriginalImplementation(); + id expected_result = reinterpret_cast<id>(3); + EXPECT_EQ(expected_result, original(object_one, @selector(method))); + } + + EXPECT_EQ(3, [object_one method]); +} + +TEST(ObjCClassSwizzlerTest, SwizzleViaInheritance) { + base::scoped_nsobject<ObjCClassSwizzlerTestOneChild> child( + [[ObjCClassSwizzlerTestOneChild alloc] init]); + EXPECT_EQ(3, [child method]); + + { + base::mac::ScopedObjCClassSwizzler swizzler( + [ObjCClassSwizzlerTestOneChild class], + @selector(method), + @selector(childAlternate)); + EXPECT_EQ(15, [child method]); + + IMP original = swizzler.GetOriginalImplementation(); + id expected_result = reinterpret_cast<id>(3); + EXPECT_EQ(expected_result, original(child, @selector(method))); + } + + EXPECT_EQ(3, [child method]); +} + +} // namespace mac +} // namespace base diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm index c48d6cc..71c0efa 100644 --- a/chrome/browser/chrome_browser_application_mac.mm +++ b/chrome/browser/chrome_browser_application_mac.mm @@ -10,13 +10,13 @@ #import "base/logging.h" #import "base/mac/scoped_nsexception_enabler.h" #import "base/mac/scoped_nsobject.h" +#import "base/mac/scoped_objc_class_swizzler.h" #import "base/metrics/histogram.h" #include "base/strings/stringprintf.h" #import "base/strings/sys_string_conversions.h" #import "chrome/browser/app_controller_mac.h" #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" #include "chrome/common/crash_keys.h" -#import "chrome/common/mac/objc_method_swizzle.h" #import "chrome/common/mac/objc_zombie.h" #include "content/public/browser/browser_accessibility_state.h" #include "content/public/browser/render_view_host.h" @@ -63,6 +63,7 @@ static IMP gOriginalInitIMP = NULL; userInfo:(NSDictionary*)someUserInfo { // Method only called when swizzled. DCHECK(_cmd == @selector(initWithName:reason:userInfo:)); + DCHECK(gOriginalInitIMP); // Parts of Cocoa rely on creating and throwing exceptions. These are not // worth bugging-out over. It is very important that there be zero chance that @@ -235,10 +236,12 @@ void SwizzleInit() { // Do-nothing wrapper so that we can arrange to only swizzle // -[NSException raise] when DCHECK() is turned on (as opposed to // replicating the preprocess logic which turns DCHECK() on). - gOriginalInitIMP = ObjcEvilDoers::SwizzleImplementedInstanceMethods( - [NSException class], - @selector(initWithName:reason:userInfo:), - @selector(crInitWithName:reason:userInfo:)); + CR_DEFINE_STATIC_LOCAL(base::mac::ScopedObjCClassSwizzler, + swizzle_exception, + ([NSException class], + @selector(initWithName:reason:userInfo:), + @selector(crInitWithName:reason:userInfo:))); + gOriginalInitIMP = swizzle_exception.GetOriginalImplementation(); } } // namespace diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index f23a6af..e41ab38 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -136,8 +136,6 @@ 'common/mac/cfbundle_blocker.mm', 'common/mac/launchd.h', 'common/mac/launchd.mm', - 'common/mac/objc_method_swizzle.h', - 'common/mac/objc_method_swizzle.mm', 'common/mac/objc_zombie.h', 'common/mac/objc_zombie.mm', 'common/media/webrtc_logging_messages.h', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 120ef4a..364ac87 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -1881,7 +1881,6 @@ 'common/mac/cfbundle_blocker_unittest.mm', 'common/mac/mock_launchd.cc', 'common/mac/mock_launchd.h', - 'common/mac/objc_method_swizzle_unittest.mm', 'common/mac/objc_zombie_unittest.mm', 'common/multi_process_lock_unittest.cc', 'common/net/x509_certificate_model_unittest.cc', diff --git a/chrome/common/mac/objc_method_swizzle.h b/chrome/common/mac/objc_method_swizzle.h deleted file mode 100644 index f756fa3..0000000 --- a/chrome/common/mac/objc_method_swizzle.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2011 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 CHROME_COMMON_MAC_OBJC_METHOD_SWIZZLE_H_ -#define CHROME_COMMON_MAC_OBJC_METHOD_SWIZZLE_H_ - -#import <objc/runtime.h> - -// You should think twice every single time you use anything from this -// namespace. -namespace ObjcEvilDoers { - -// This is similar to class_getInstanceMethod(), except that it -// returns NULL if |aClass| does not directly implement |aSelector|. -Method GetImplementedInstanceMethod(Class aClass, SEL aSelector); - -// Exchanges the implementation of |originalSelector| and -// |alternateSelector| within |aClass|. Both selectors must be -// implemented directly by |aClass|, not inherited. The IMP returned -// is for |originalSelector| (for purposes of forwarding). -IMP SwizzleImplementedInstanceMethods( - Class aClass, const SEL originalSelector, const SEL alternateSelector); - -} // namespace ObjcEvilDoers - -#endif // CHROME_COMMON_MAC_OBJC_METHOD_SWIZZLE_H_ diff --git a/chrome/common/mac/objc_method_swizzle.mm b/chrome/common/mac/objc_method_swizzle.mm deleted file mode 100644 index 62b630a..0000000 --- a/chrome/common/mac/objc_method_swizzle.mm +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2011 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 "chrome/common/mac/objc_method_swizzle.h" - -#import "base/logging.h" - -namespace ObjcEvilDoers { - -Method GetImplementedInstanceMethod(Class aClass, SEL aSelector) { - Method method = NULL; - unsigned int methodCount = 0; - Method* methodList = class_copyMethodList(aClass, &methodCount); - if (methodList) { - for (unsigned int i = 0; i < methodCount; ++i) { - if (method_getName(methodList[i]) == aSelector) { - method = methodList[i]; - break; - } - } - free(methodList); - } - return method; -} - -IMP SwizzleImplementedInstanceMethods( - Class aClass, const SEL originalSelector, const SEL alternateSelector) { - // The methods must both be implemented by the target class, not - // inherited from a superclass. - Method original = GetImplementedInstanceMethod(aClass, originalSelector); - Method alternate = GetImplementedInstanceMethod(aClass, alternateSelector); - DCHECK(original); - DCHECK(alternate); - if (!original || !alternate) { - return NULL; - } - - // The argument and return types must match exactly. - const char* originalTypes = method_getTypeEncoding(original); - const char* alternateTypes = method_getTypeEncoding(alternate); - DCHECK(originalTypes); - DCHECK(alternateTypes); - DCHECK(0 == strcmp(originalTypes, alternateTypes)); - if (!originalTypes || !alternateTypes || - strcmp(originalTypes, alternateTypes)) { - return NULL; - } - - IMP ret = method_getImplementation(original); - if (ret) { - method_exchangeImplementations(original, alternate); - } - return ret; -} - -} // namespace ObjcEvilDoers diff --git a/chrome/common/mac/objc_method_swizzle_unittest.mm b/chrome/common/mac/objc_method_swizzle_unittest.mm deleted file mode 100644 index 3053f3b7..0000000 --- a/chrome/common/mac/objc_method_swizzle_unittest.mm +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2011 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 "chrome/common/mac/objc_method_swizzle.h" - -#include "base/mac/scoped_nsobject.h" -#include "testing/gtest/include/gtest/gtest.h" - -@interface ObjcMethodSwizzleTest : NSObject -- (id)self; - -- (NSInteger)one; -- (NSInteger)two; -@end - -@implementation ObjcMethodSwizzleTest : NSObject -- (id)self { - return [super self]; -} - -- (NSInteger)one { - return 1; -} -- (NSInteger)two { - return 2; -} -@end - -@interface ObjcMethodSwizzleTest (ObjcMethodSwizzleTestCategory) -- (NSUInteger)hash; -@end - -@implementation ObjcMethodSwizzleTest (ObjcMethodSwizzleTestCategory) -- (NSUInteger)hash { - return [super hash]; -} -@end - -namespace ObjcEvilDoers { - -TEST(ObjcMethodSwizzleTest, GetImplementedInstanceMethod) { - EXPECT_EQ(class_getInstanceMethod([NSObject class], @selector(dealloc)), - GetImplementedInstanceMethod([NSObject class], @selector(dealloc))); - EXPECT_EQ(class_getInstanceMethod([NSObject class], @selector(self)), - GetImplementedInstanceMethod([NSObject class], @selector(self))); - EXPECT_EQ(class_getInstanceMethod([NSObject class], @selector(hash)), - GetImplementedInstanceMethod([NSObject class], @selector(hash))); - - Class testClass = [ObjcMethodSwizzleTest class]; - EXPECT_EQ(class_getInstanceMethod(testClass, @selector(self)), - GetImplementedInstanceMethod(testClass, @selector(self))); - EXPECT_NE(class_getInstanceMethod([NSObject class], @selector(self)), - class_getInstanceMethod(testClass, @selector(self))); - - EXPECT_TRUE(class_getInstanceMethod(testClass, @selector(dealloc))); - EXPECT_FALSE(GetImplementedInstanceMethod(testClass, @selector(dealloc))); -} - -TEST(ObjcMethodSwizzleTest, SwizzleImplementedInstanceMethods) { - base::scoped_nsobject<ObjcMethodSwizzleTest> object( - [[ObjcMethodSwizzleTest alloc] init]); - EXPECT_EQ([object one], 1); - EXPECT_EQ([object two], 2); - - Class testClass = [object class]; - SwizzleImplementedInstanceMethods(testClass, @selector(one), @selector(two)); - EXPECT_EQ([object one], 2); - EXPECT_EQ([object two], 1); - - SwizzleImplementedInstanceMethods(testClass, @selector(one), @selector(two)); - EXPECT_EQ([object one], 1); - EXPECT_EQ([object two], 2); -} - -} // namespace ObjcEvilDoers diff --git a/chrome/common/mac/objc_zombie.mm b/chrome/common/mac/objc_zombie.mm index d0cb063..b869993 100644 --- a/chrome/common/mac/objc_zombie.mm +++ b/chrome/common/mac/objc_zombie.mm @@ -19,7 +19,6 @@ #include "base/strings/stringprintf.h" #include "base/synchronization/lock.h" #include "chrome/common/crash_keys.h" -#import "chrome/common/mac/objc_method_swizzle.h" #if !defined(OS_IOS) && (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6) // Apparently objc/runtime.h doesn't define this with the 10.6 SDK yet. diff --git a/ui/base/cocoa/cocoa_base_utils_unittest.mm b/ui/base/cocoa/cocoa_base_utils_unittest.mm index 5749e2d..f379120 100644 --- a/ui/base/cocoa/cocoa_base_utils_unittest.mm +++ b/ui/base/cocoa/cocoa_base_utils_unittest.mm @@ -6,6 +6,7 @@ #import <objc/objc-class.h> +#import "base/mac/scoped_objc_class_swizzler.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "ui/events/event_constants.h" @@ -39,8 +40,8 @@ TEST_F(CocoaBaseUtilsTest, WindowOpenDispositionFromNSEvent) { // Shift+Middle Click = new foreground tab. { - ScopedClassSwizzler swizzler([NSEvent class], [TestEvent class], - @selector(modifierFlags)); + base::mac::ScopedObjCClassSwizzler swizzler( + [NSEvent class], [TestEvent class], @selector(modifierFlags)); me = cocoa_test_event_utils::MouseEventWithType(NSOtherMouseUp, NSShiftKeyMask); EXPECT_EQ(NEW_FOREGROUND_TAB, WindowOpenDispositionFromNSEvent(me)); diff --git a/ui/events/cocoa/events_mac_unittest.mm b/ui/events/cocoa/events_mac_unittest.mm index 77f8549..f58cfd0 100644 --- a/ui/events/cocoa/events_mac_unittest.mm +++ b/ui/events/cocoa/events_mac_unittest.mm @@ -7,6 +7,7 @@ #import <Cocoa/Cocoa.h> #include "base/mac/scoped_cftyperef.h" +#import "base/mac/scoped_objc_class_swizzler.h" #include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/event_constants.h" @@ -32,7 +33,7 @@ NSWindow* g_test_window = nil; @end @implementation MiddleMouseButtonNumberDonor -- (NSUInteger)buttonNumber { return 2; } +- (NSInteger)buttonNumber { return 2; } @end @implementation TestWindowDonor @@ -57,7 +58,7 @@ class EventsMacTest : public CocoaTest { void SwizzleMiddleMouseButton() { DCHECK(!swizzler_); - swizzler_.reset(new ScopedClassSwizzler( + swizzler_.reset(new base::mac::ScopedObjCClassSwizzler( [NSEvent class], [MiddleMouseButtonNumberDonor class], @selector(buttonNumber))); @@ -67,10 +68,8 @@ class EventsMacTest : public CocoaTest { DCHECK(!g_test_window); DCHECK(!swizzler_); g_test_window = test_window(); - swizzler_.reset(new ScopedClassSwizzler( - [NSEvent class], - [TestWindowDonor class], - @selector(window))); + swizzler_.reset(new base::mac::ScopedObjCClassSwizzler( + [NSEvent class], [TestWindowDonor class], @selector(window))); } void ClearSwizzle() { @@ -117,7 +116,7 @@ class EventsMacTest : public CocoaTest { } private: - scoped_ptr<ScopedClassSwizzler> swizzler_; + scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzler_; DISALLOW_COPY_AND_ASSIGN(EventsMacTest); }; diff --git a/ui/events/test/cocoa_test_event_utils.h b/ui/events/test/cocoa_test_event_utils.h index 6c4994d..76c6a32 100644 --- a/ui/events/test/cocoa_test_event_utils.h +++ b/ui/events/test/cocoa_test_event_utils.h @@ -11,20 +11,6 @@ #include "base/basictypes.h" -// Within a given scope, replace the selector |selector| on |target| with that -// from |source|. -class ScopedClassSwizzler { - public: - ScopedClassSwizzler(Class target, Class source, SEL selector); - ~ScopedClassSwizzler(); - - private: - Method old_selector_impl_; - Method new_selector_impl_; - - DISALLOW_COPY_AND_ASSIGN(ScopedClassSwizzler); -}; - namespace cocoa_test_event_utils { // Create synthetic mouse events for testing. Currently these are very diff --git a/ui/events/test/cocoa_test_event_utils.mm b/ui/events/test/cocoa_test_event_utils.mm index 4f0cb67..2694b84e 100644 --- a/ui/events/test/cocoa_test_event_utils.mm +++ b/ui/events/test/cocoa_test_event_utils.mm @@ -6,22 +6,6 @@ #include "ui/events/test/cocoa_test_event_utils.h" -ScopedClassSwizzler::ScopedClassSwizzler(Class target, Class source, - SEL selector) { - old_selector_impl_ = class_getInstanceMethod(target, selector); - new_selector_impl_ = class_getInstanceMethod(source, selector); - if (!old_selector_impl_ && !new_selector_impl_) { - // Try class methods. - old_selector_impl_ = class_getClassMethod(target, selector); - new_selector_impl_ = class_getClassMethod(source, selector); - } - method_exchangeImplementations(old_selector_impl_, new_selector_impl_); -} - -ScopedClassSwizzler::~ScopedClassSwizzler() { - method_exchangeImplementations(old_selector_impl_, new_selector_impl_); -} - namespace cocoa_test_event_utils { NSEvent* MouseEventAtPoint(NSPoint point, NSEventType type, diff --git a/ui/views/test/event_generator_delegate_mac.mm b/ui/views/test/event_generator_delegate_mac.mm index d0e351a..db94d34 100644 --- a/ui/views/test/event_generator_delegate_mac.mm +++ b/ui/views/test/event_generator_delegate_mac.mm @@ -4,13 +4,13 @@ #import <Cocoa/Cocoa.h> +#import "base/mac/scoped_objc_class_swizzler.h" #include "base/memory/singleton.h" #include "ui/events/event_processor.h" #include "ui/events/event_target.h" #include "ui/events/event_target_iterator.h" #include "ui/events/event_targeter.h" #include "ui/events/test/event_generator.h" -#import "ui/events/test/cocoa_test_event_utils.h" #include "ui/gfx/mac/coordinate_conversion.h" namespace { @@ -293,7 +293,7 @@ class EventGeneratorDelegateMac : public ui::EventTarget, ui::test::EventGenerator* owner_; NSWindow* window_; - scoped_ptr<ScopedClassSwizzler> swizzle_pressed_; + scoped_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_pressed_; DISALLOW_COPY_AND_ASSIGN(EventGeneratorDelegateMac); }; @@ -332,7 +332,7 @@ void EventGeneratorDelegateMac::SetContext(ui::test::EventGenerator* owner, owner_ = owner; window_ = window; if (owner_) { - swizzle_pressed_.reset(new ScopedClassSwizzler( + swizzle_pressed_.reset(new base::mac::ScopedObjCClassSwizzler( [NSEvent class], [NSEventDonor class], @selector(pressedMouseButtons))); |