Commit 3ef60b75 authored by Elly Fong-Jones's avatar Elly Fong-Jones Committed by Commit Bot

mac newsdk: don't depend on definition of IMP

As of the 10.15 SDK IMP has changed from:
  id (*IMP)(id receiver, SEL selector, ...);
to:
  void (*IMP)(void);
thus requiring a cast to call it. Rather than having this cast at
every place that invokes an IMP, this change adds a new method to
ScopedObjCClassSwizzler to allow invoking the original method from
the swizzler, which accounts for every invocation of IMP in the tree.

TBR=avi@chromium.org

Bug: 973128
Change-Id: I13eab9a79bab23e9a2c3854fb95e42de61e04d3b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1906334Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Commit-Queue: Elly Fong-Jones <ellyjones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714568}
parent 8f1c526c
......@@ -31,7 +31,17 @@ class BASE_EXPORT ScopedObjCClassSwizzler {
// Return a callable function pointer for the replaced method. To call this
// from the replacing function, the first two arguments should be |self| and
// |_cmd|. These are followed by the (variadic) method arguments.
IMP GetOriginalImplementation();
IMP GetOriginalImplementation() const;
// Invoke the original function directly, optionally with some arguments.
// Prefer this to hanging onto pointers to the original implementation
// function or to casting the result of GetOriginalImplementation() yourself.
template <typename Ret, typename... Args>
Ret InvokeOriginal(id receiver, SEL selector, Args... args) const {
auto func = reinterpret_cast<Ret (*)(id, SEL, Args...)>(
GetOriginalImplementation());
return func(receiver, selector, args...);
}
private:
// Delegated constructor.
......
......@@ -30,7 +30,7 @@ ScopedObjCClassSwizzler::~ScopedObjCClassSwizzler() {
method_exchangeImplementations(old_selector_impl_, new_selector_impl_);
}
IMP ScopedObjCClassSwizzler::GetOriginalImplementation() {
IMP ScopedObjCClassSwizzler::GetOriginalImplementation() const {
// 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_);
......
......@@ -92,9 +92,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleInstanceMethods) {
EXPECT_EQ(6, [object_one method]);
EXPECT_EQ(7, [object_two method]);
IMP original = swizzler.GetOriginalImplementation();
id expected_result = reinterpret_cast<id>(3);
EXPECT_EQ(expected_result, original(object_one, @selector(method)));
EXPECT_EQ(3, swizzler.InvokeOriginal<int>(object_one, @selector(method)));
}
EXPECT_EQ(3, [object_one method]);
......@@ -113,10 +111,8 @@ TEST(ObjCClassSwizzlerTest, SwizzleClassMethods) {
EXPECT_EQ(20, [ObjCClassSwizzlerTestOne function]);
EXPECT_EQ(10, [ObjCClassSwizzlerTestTwo function]);
IMP original = swizzler.GetOriginalImplementation();
id expected_result = reinterpret_cast<id>(10);
EXPECT_EQ(expected_result,
original([ObjCClassSwizzlerTestOne class], @selector(function)));
EXPECT_EQ(10, swizzler.InvokeOriginal<int>([ObjCClassSwizzlerTestOne class],
@selector(function)));
}
EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]);
......@@ -135,9 +131,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleViaCategory) {
@selector(alternate));
EXPECT_EQ(9, [object_one method]);
IMP original = swizzler.GetOriginalImplementation();
id expected_result = reinterpret_cast<id>(3);
EXPECT_EQ(expected_result, original(object_one, @selector(method)));
EXPECT_EQ(3, swizzler.InvokeOriginal<int>(object_one, @selector(method)));
}
EXPECT_EQ(3, [object_one method]);
......@@ -155,9 +149,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleViaInheritance) {
@selector(childAlternate));
EXPECT_EQ(15, [child method]);
IMP original = swizzler.GetOriginalImplementation();
id expected_result = reinterpret_cast<id>(3);
EXPECT_EQ(expected_result, original(child, @selector(method)));
EXPECT_EQ(3, swizzler.InvokeOriginal<int>(child, @selector(method)));
}
EXPECT_EQ(3, [child method]);
......
......@@ -63,6 +63,11 @@
using base::SysUTF16ToNSString;
@interface AppController (ForTesting)
- (void)getUrl:(NSAppleEventDescriptor*)event
withReply:(NSAppleEventDescriptor*)reply;
@end
namespace {
GURL g_open_shortcut_url = GURL::EmptyGURL();
......@@ -86,14 +91,7 @@ NSAppleEventDescriptor* AppleEventToOpenUrl(const GURL& url) {
void SendAppleEventToOpenUrlToAppController(const GURL& url) {
AppController* controller =
base::mac::ObjCCast<AppController>([NSApp delegate]);
Method get_url =
class_getInstanceMethod([controller class], @selector(getUrl:withReply:));
ASSERT_TRUE(get_url);
NSAppleEventDescriptor* shortcut_event = AppleEventToOpenUrl(url);
method_invoke(controller, get_url, shortcut_event, NULL);
[controller getUrl:AppleEventToOpenUrl(url) withReply:nullptr];
}
void RunClosureWhenProfileInitialized(const base::Closure& closure,
......
......@@ -20,7 +20,7 @@
namespace {
IMP g_original_populatemenu_implementation = nullptr;
base::mac::ScopedObjCClassSwizzler* g_populatemenu_swizzler = nullptr;
// |g_filtered_entries_array| is only set during testing (see
// +[ChromeSwizzleServicesMenuUpdater storeFilteredEntriesForTestingInArray:]).
......@@ -98,8 +98,8 @@ NSMenuItem* GetMenuItemByID(ui::MenuModel* model,
}
// Pass the filtered array along to the _NSServicesMenuUpdater.
g_original_populatemenu_implementation(self, _cmd, menu, remainingEntries,
display);
g_populatemenu_swizzler->InvokeOriginal<void, NSMenu*, NSArray*, BOOL>(
self, _cmd, menu, remainingEntries, display);
}
+ (void)storeFilteredEntriesForTestingInArray:(NSMutableArray*)array {
......@@ -145,8 +145,7 @@ NSMenuItem* GetMenuItemByID(ui::MenuModel* model,
Class swizzleClass = [ChromeSwizzleServicesMenuUpdater class];
static base::NoDestructor<base::mac::ScopedObjCClassSwizzler>
servicesMenuFilter(targetClass, swizzleClass, targetSelector);
g_original_populatemenu_implementation =
servicesMenuFilter->GetOriginalImplementation();
g_populatemenu_swizzler = servicesMenuFilter.get();
});
}
......
......@@ -29,7 +29,9 @@ class SendGlobalKeyEventsHelper {
// Callback for MockCrApplication.
void ObserveSendEvent(NSEvent* event);
IMP original_send_event() const { return original_send_event_; }
void OriginalSendEvent(id receiver, SEL selector, NSEvent* event) {
scoped_swizzler_->InvokeOriginal<void, NSEvent*>(receiver, selector, event);
}
void SendGlobalKeyEventsAndWait(int key_code, int modifier_flags);
......@@ -39,7 +41,6 @@ class SendGlobalKeyEventsHelper {
bool key_down);
std::unique_ptr<base::mac::ScopedObjCClassSwizzler> scoped_swizzler_;
IMP original_send_event_ = nullptr;
base::ScopedCFTypeRef<CGEventSourceRef> event_source_;
CGEventTapLocation event_tap_location_;
base::RunLoop run_loop_;
......@@ -62,7 +63,7 @@ SendGlobalKeyEventsHelper* g_global_key_events_helper = nullptr;
- (void)sendEvent:(NSEvent*)event {
DCHECK(g_global_key_events_helper);
g_global_key_events_helper->ObserveSendEvent(event);
g_global_key_events_helper->original_send_event()(self, _cmd, event);
g_global_key_events_helper->OriginalSendEvent(self, _cmd, event);
}
@end
......@@ -78,7 +79,6 @@ SendGlobalKeyEventsHelper::SendGlobalKeyEventsHelper()
scoped_swizzler_ = std::make_unique<base::mac::ScopedObjCClassSwizzler>(
[BrowserCrApplication class], [MockCrApplication class],
@selector(sendEvent:));
original_send_event_ = scoped_swizzler_->GetOriginalImplementation();
}
SendGlobalKeyEventsHelper::~SendGlobalKeyEventsHelper() {
......
......@@ -163,7 +163,7 @@ void GetStringFromRangeForRenderWidget(
- (void)didAddSubview:(NSView*)view {
content::RenderWidgetHostViewCocoaObserver::GetSwizzler(
content::RenderWidgetHostViewCocoaObserver::kDidAddSubview)
->GetOriginalImplementation()(self, _cmd, view);
->InvokeOriginal<void, NSView*>(self, _cmd, view);
content::RenderWidgetHostViewMac* rwhv_mac =
content::GetRenderWidgetHostViewMac(self);
......@@ -206,7 +206,8 @@ void GetStringFromRangeForRenderWidget(
content::RenderWidgetHostViewCocoaObserver::GetSwizzler(
content::RenderWidgetHostViewCocoaObserver::
kShowDefinitionForAttributedString)
->GetOriginalImplementation()(self, _cmd, attrString, textBaselineOrigin);
->InvokeOriginal<void, NSAttributedString*, NSPoint>(
self, _cmd, attrString, textBaselineOrigin);
auto* rwhv_mac = content::GetRenderWidgetHostViewMac(self);
......
......@@ -14,7 +14,7 @@ using base::mac::ScopedObjCClassSwizzler;
namespace {
NSWindow* g_fake_focused_window = nil;
IMP g_order_out_impl_ = nullptr;
base::mac::ScopedObjCClassSwizzler* g_order_out_swizzler = nullptr;
void SetFocus(NSWindow* window) {
g_fake_focused_window = window;
......@@ -74,7 +74,7 @@ void ClearFocus() {
NSWindow* selfAsWindow = base::mac::ObjCCastStrict<NSWindow>(self);
if (selfAsWindow == g_fake_focused_window)
ClearFocus();
g_order_out_impl_(self, _cmd, sender);
g_order_out_swizzler->InvokeOriginal<void, id>(self, _cmd, sender);
}
- (void)resignKeyWindow {
......@@ -117,10 +117,11 @@ ScopedFakeNSWindowFocus::ScopedFakeNSWindowFocus()
new ScopedObjCClassSwizzler([NSWindow class],
[FakeNSWindowFocusDonor class],
@selector(orderOut:))) {
g_order_out_impl_ = order_out_swizzler_->GetOriginalImplementation();
g_order_out_swizzler = order_out_swizzler_.get();
}
ScopedFakeNSWindowFocus::~ScopedFakeNSWindowFocus() {
g_order_out_swizzler = nullptr;
ClearFocus();
}
......
......@@ -61,14 +61,14 @@ class ScopedFakeNSWindowFullscreen::Impl {
}
}
IMP SetStyleMaskImplementation() {
return set_style_mask_swizzler_.GetOriginalImplementation();
void OriginalSetStyleMask(id receiver, SEL selector, NSUInteger mask) {
return set_style_mask_swizzler_.InvokeOriginal<void, NSUInteger>(
receiver, selector, mask);
}
NSUInteger StyleMaskForWindow(NSWindow* window) {
NSUInteger actual_style_mask = reinterpret_cast<NSUInteger>(
style_mask_swizzler_.GetOriginalImplementation()(window,
@selector(styleMask)));
auto actual_style_mask = style_mask_swizzler_.InvokeOriginal<NSUInteger>(
window, @selector(styleMask));
if (window_ != window || !style_as_fullscreen_)
return actual_style_mask;
......@@ -233,7 +233,7 @@ void ScopedFakeNSWindowFullscreen::FinishTransition() {
NOTREACHED() << "Can't set NSFullScreenWindowMask while faking fullscreen.";
}
newMask &= ~NSFullScreenWindowMask;
g_fake_fullscreen_impl->SetStyleMaskImplementation()(self, _cmd, newMask);
g_fake_fullscreen_impl->OriginalSetStyleMask(self, _cmd, newMask);
}
@end
......@@ -252,8 +252,8 @@ class EventGeneratorDelegateMac : public ui::EventTarget,
static EventGeneratorDelegateMac* instance() { return instance_; }
IMP CurrentEventMethod() {
return swizzle_current_event_->GetOriginalImplementation();
NSEvent* OriginalCurrentEvent(id receiver, SEL selector) {
return swizzle_current_event_->InvokeOriginal<NSEvent*>(receiver, selector);
}
NSWindow* window() { return window_.get(); }
......@@ -634,8 +634,8 @@ CreateEventGeneratorDelegateMac(ui::test::EventGenerator* owner,
return g_current_event;
// Find the original implementation and invoke it.
IMP original = EventGeneratorDelegateMac::instance()->CurrentEventMethod();
return original(self, _cmd);
return EventGeneratorDelegateMac::instance()->OriginalCurrentEvent(self,
_cmd);
}
@end
......@@ -1139,8 +1139,8 @@ class ScopedSwizzleWaiter {
~ScopedSwizzleWaiter() { instance_ = nullptr; }
static IMP GetMethodAndMarkCalled() {
return instance_->GetMethodInternal();
static void OriginalSetWindowStateForEnd(id receiver, SEL method) {
return instance_->CallMethodInternal(receiver, method);
}
void WaitForMethod() {
......@@ -1158,12 +1158,12 @@ class ScopedSwizzleWaiter {
bool method_called() const { return method_called_; }
private:
IMP GetMethodInternal() {
void CallMethodInternal(id receiver, SEL selector) {
DCHECK(!method_called_);
method_called_ = true;
if (run_loop_)
run_loop_->Quit();
return swizzler_.GetOriginalImplementation();
swizzler_.InvokeOriginal<void>(receiver, selector);
}
static ScopedSwizzleWaiter* instance_;
......@@ -2475,7 +2475,7 @@ TEST_F(NativeWidgetMacTest, InitCallback) {
@implementation TestStopAnimationWaiter
- (void)setWindowStateForEnd {
views::test::ScopedSwizzleWaiter::GetMethodAndMarkCalled()(self, _cmd);
views::test::ScopedSwizzleWaiter::OriginalSetWindowStateForEnd(self, _cmd);
}
@end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment