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