xref: /aosp_15_r20/external/cronet/base/apple/scoped_objc_class_swizzler.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_APPLE_SCOPED_OBJC_CLASS_SWIZZLER_H_
6 #define BASE_APPLE_SCOPED_OBJC_CLASS_SWIZZLER_H_
7 
8 #import <objc/runtime.h>
9 
10 #include "base/base_export.h"
11 
12 namespace base::apple {
13 
14 // Within a given scope, swaps method implementations of a class interface, or
15 // between two class interfaces. The argument and return types must match.
16 class BASE_EXPORT ScopedObjCClassSwizzler {
17  public:
18   // Given two classes that each respond to |selector|, swap the implementations
19   // of those methods.
20   ScopedObjCClassSwizzler(Class target, Class source, SEL selector);
21 
22   // Given two selectors on the same class interface, |target| (e.g. via
23   // inheritance or categories), swap the implementations of methods |original|
24   // and |alternate|.
25   ScopedObjCClassSwizzler(Class target, SEL original, SEL alternate);
26 
27   ScopedObjCClassSwizzler(const ScopedObjCClassSwizzler&) = delete;
28   ScopedObjCClassSwizzler& operator=(const ScopedObjCClassSwizzler&) = delete;
29 
30   ~ScopedObjCClassSwizzler();
31 
32   // Return a callable function pointer for the replaced method. To call this
33   // from the replacing function, the first two arguments should be |self| and
34   // |_cmd|. These are followed by the (variadic) method arguments.
35   IMP GetOriginalImplementation() const;
36 
37   // Invoke the original function directly, optionally with some arguments.
38   // Prefer this to hanging onto pointers to the original implementation
39   // function or to casting the result of GetOriginalImplementation() yourself.
40   template <typename Ret, typename... Args>
InvokeOriginal(id receiver,SEL selector,Args...args)41   Ret InvokeOriginal(id receiver, SEL selector, Args... args) const {
42     auto func = reinterpret_cast<Ret (*)(id, SEL, Args...)>(
43         GetOriginalImplementation());
44     return func(receiver, selector, args...);
45   }
46 
47  private:
48   // Delegated constructor.
49   void Init(Class target, Class source, SEL original, SEL alternate);
50 
51   Method old_selector_impl_;
52   Method new_selector_impl_;
53 };
54 
55 }  // namespace base::apple
56 
57 #endif  // BASE_APPLE_SCOPED_OBJC_CLASS_SWIZZLER_H_
58