mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 00:06:09 +03:00
72 lines
2.5 KiB
Plaintext
72 lines
2.5 KiB
Plaintext
|
// 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
|