1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "base/mac/scoped_objc_class_swizzler.h"
9 #include "base/logging.h"
14 ScopedObjCClassSwizzler::ScopedObjCClassSwizzler(Class target,
17 : old_selector_impl_(NULL), new_selector_impl_(NULL) {
18 Init(target, source, selector, selector);
21 ScopedObjCClassSwizzler::ScopedObjCClassSwizzler(Class target,
24 : old_selector_impl_(NULL), new_selector_impl_(NULL) {
25 Init(target, target, original, alternate);
28 ScopedObjCClassSwizzler::~ScopedObjCClassSwizzler() {
29 if (old_selector_impl_ && new_selector_impl_)
30 method_exchangeImplementations(old_selector_impl_, new_selector_impl_);
33 IMP ScopedObjCClassSwizzler::GetOriginalImplementation() {
34 // Note that while the swizzle is in effect the "new" method is actually
35 // pointing to the original implementation, since they have been swapped.
36 return method_getImplementation(new_selector_impl_);
39 void ScopedObjCClassSwizzler::Init(Class target,
43 old_selector_impl_ = class_getInstanceMethod(target, original);
44 new_selector_impl_ = class_getInstanceMethod(source, alternate);
45 if (!old_selector_impl_ && !new_selector_impl_) {
47 old_selector_impl_ = class_getClassMethod(target, original);
48 new_selector_impl_ = class_getClassMethod(source, alternate);
51 DCHECK(old_selector_impl_);
52 DCHECK(new_selector_impl_);
53 if (!old_selector_impl_ || !new_selector_impl_)
56 // The argument and return types must match exactly.
57 const char* old_types = method_getTypeEncoding(old_selector_impl_);
58 const char* new_types = method_getTypeEncoding(new_selector_impl_);
61 DCHECK_EQ(0, strcmp(old_types, new_types));
62 if (!old_types || !new_types || strcmp(old_types, new_types)) {
63 old_selector_impl_ = new_selector_impl_ = NULL;
67 method_exchangeImplementations(old_selector_impl_, new_selector_impl_);