• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2011 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.
4
5#import "chrome/common/mac/objc_method_swizzle.h"
6
7#import "base/logging.h"
8
9namespace ObjcEvilDoers {
10
11Method GetImplementedInstanceMethod(Class aClass, SEL aSelector) {
12  Method method = NULL;
13  unsigned int methodCount = 0;
14  Method* methodList = class_copyMethodList(aClass, &methodCount);
15  if (methodList) {
16    for (unsigned int i = 0; i < methodCount; ++i) {
17      if (method_getName(methodList[i]) == aSelector) {
18        method = methodList[i];
19        break;
20      }
21    }
22    free(methodList);
23  }
24  return method;
25}
26
27IMP SwizzleImplementedInstanceMethods(
28    Class aClass, const SEL originalSelector, const SEL alternateSelector) {
29  // The methods must both be implemented by the target class, not
30  // inherited from a superclass.
31  Method original = GetImplementedInstanceMethod(aClass, originalSelector);
32  Method alternate = GetImplementedInstanceMethod(aClass, alternateSelector);
33  DCHECK(original);
34  DCHECK(alternate);
35  if (!original || !alternate) {
36    return NULL;
37  }
38
39  // The argument and return types must match exactly.
40  const char* originalTypes = method_getTypeEncoding(original);
41  const char* alternateTypes = method_getTypeEncoding(alternate);
42  DCHECK(originalTypes);
43  DCHECK(alternateTypes);
44  DCHECK(0 == strcmp(originalTypes, alternateTypes));
45  if (!originalTypes || !alternateTypes ||
46      strcmp(originalTypes, alternateTypes)) {
47    return NULL;
48  }
49
50  IMP ret = method_getImplementation(original);
51  if (ret) {
52    method_exchangeImplementations(original, alternate);
53  }
54  return ret;
55}
56
57}  // namespace ObjcEvilDoers
58