summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortapted@chromium.org <tapted@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-12 12:03:48 +0000
committertapted@chromium.org <tapted@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-12 12:05:27 +0000
commit0b7f85234f13b9e644cb63be4b560a26e0c09c2e (patch)
treef2e0695554513feb1c32f1d9410c59b8bc97da72
parent5f01d48039db9d83409290e3f2ebd5c159e97a9e (diff)
downloadchromium_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.gn3
-rw-r--r--base/base.gyp1
-rw-r--r--base/base.gypi2
-rw-r--r--base/mac/scoped_objc_class_swizzler.h49
-rw-r--r--base/mac/scoped_objc_class_swizzler.mm71
-rw-r--r--base/mac/scoped_objc_class_swizzler_unittest.mm166
-rw-r--r--chrome/browser/chrome_browser_application_mac.mm13
-rw-r--r--chrome/chrome_common.gypi2
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--chrome/common/mac/objc_method_swizzle.h27
-rw-r--r--chrome/common/mac/objc_method_swizzle.mm57
-rw-r--r--chrome/common/mac/objc_method_swizzle_unittest.mm76
-rw-r--r--chrome/common/mac/objc_zombie.mm1
-rw-r--r--ui/base/cocoa/cocoa_base_utils_unittest.mm5
-rw-r--r--ui/events/cocoa/events_mac_unittest.mm13
-rw-r--r--ui/events/test/cocoa_test_event_utils.h14
-rw-r--r--ui/events/test/cocoa_test_event_utils.mm16
-rw-r--r--ui/views/test/event_generator_delegate_mac.mm6
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)));