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 { ...@@ -31,7 +31,17 @@ class BASE_EXPORT ScopedObjCClassSwizzler {
// Return a callable function pointer for the replaced method. To call this // Return a callable function pointer for the replaced method. To call this
// from the replacing function, the first two arguments should be |self| and // from the replacing function, the first two arguments should be |self| and
// |_cmd|. These are followed by the (variadic) method arguments. // |_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: private:
// Delegated constructor. // Delegated constructor.
......
...@@ -30,7 +30,7 @@ ScopedObjCClassSwizzler::~ScopedObjCClassSwizzler() { ...@@ -30,7 +30,7 @@ ScopedObjCClassSwizzler::~ScopedObjCClassSwizzler() {
method_exchangeImplementations(old_selector_impl_, new_selector_impl_); 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 // Note that while the swizzle is in effect the "new" method is actually
// pointing to the original implementation, since they have been swapped. // pointing to the original implementation, since they have been swapped.
return method_getImplementation(new_selector_impl_); return method_getImplementation(new_selector_impl_);
......
...@@ -92,9 +92,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleInstanceMethods) { ...@@ -92,9 +92,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleInstanceMethods) {
EXPECT_EQ(6, [object_one method]); EXPECT_EQ(6, [object_one method]);
EXPECT_EQ(7, [object_two method]); EXPECT_EQ(7, [object_two method]);
IMP original = swizzler.GetOriginalImplementation(); EXPECT_EQ(3, swizzler.InvokeOriginal<int>(object_one, @selector(method)));
id expected_result = reinterpret_cast<id>(3);
EXPECT_EQ(expected_result, original(object_one, @selector(method)));
} }
EXPECT_EQ(3, [object_one method]); EXPECT_EQ(3, [object_one method]);
...@@ -113,10 +111,8 @@ TEST(ObjCClassSwizzlerTest, SwizzleClassMethods) { ...@@ -113,10 +111,8 @@ TEST(ObjCClassSwizzlerTest, SwizzleClassMethods) {
EXPECT_EQ(20, [ObjCClassSwizzlerTestOne function]); EXPECT_EQ(20, [ObjCClassSwizzlerTestOne function]);
EXPECT_EQ(10, [ObjCClassSwizzlerTestTwo function]); EXPECT_EQ(10, [ObjCClassSwizzlerTestTwo function]);
IMP original = swizzler.GetOriginalImplementation(); EXPECT_EQ(10, swizzler.InvokeOriginal<int>([ObjCClassSwizzlerTestOne class],
id expected_result = reinterpret_cast<id>(10); @selector(function)));
EXPECT_EQ(expected_result,
original([ObjCClassSwizzlerTestOne class], @selector(function)));
} }
EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]); EXPECT_EQ(10, [ObjCClassSwizzlerTestOne function]);
...@@ -135,9 +131,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleViaCategory) { ...@@ -135,9 +131,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleViaCategory) {
@selector(alternate)); @selector(alternate));
EXPECT_EQ(9, [object_one method]); EXPECT_EQ(9, [object_one method]);
IMP original = swizzler.GetOriginalImplementation(); EXPECT_EQ(3, swizzler.InvokeOriginal<int>(object_one, @selector(method)));
id expected_result = reinterpret_cast<id>(3);
EXPECT_EQ(expected_result, original(object_one, @selector(method)));
} }
EXPECT_EQ(3, [object_one method]); EXPECT_EQ(3, [object_one method]);
...@@ -155,9 +149,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleViaInheritance) { ...@@ -155,9 +149,7 @@ TEST(ObjCClassSwizzlerTest, SwizzleViaInheritance) {
@selector(childAlternate)); @selector(childAlternate));
EXPECT_EQ(15, [child method]); EXPECT_EQ(15, [child method]);
IMP original = swizzler.GetOriginalImplementation(); EXPECT_EQ(3, swizzler.InvokeOriginal<int>(child, @selector(method)));
id expected_result = reinterpret_cast<id>(3);
EXPECT_EQ(expected_result, original(child, @selector(method)));
} }
EXPECT_EQ(3, [child method]); EXPECT_EQ(3, [child method]);
......
...@@ -63,6 +63,11 @@ ...@@ -63,6 +63,11 @@
using base::SysUTF16ToNSString; using base::SysUTF16ToNSString;
@interface AppController (ForTesting)
- (void)getUrl:(NSAppleEventDescriptor*)event
withReply:(NSAppleEventDescriptor*)reply;
@end
namespace { namespace {
GURL g_open_shortcut_url = GURL::EmptyGURL(); GURL g_open_shortcut_url = GURL::EmptyGURL();
...@@ -86,14 +91,7 @@ NSAppleEventDescriptor* AppleEventToOpenUrl(const GURL& url) { ...@@ -86,14 +91,7 @@ NSAppleEventDescriptor* AppleEventToOpenUrl(const GURL& url) {
void SendAppleEventToOpenUrlToAppController(const GURL& url) { void SendAppleEventToOpenUrlToAppController(const GURL& url) {
AppController* controller = AppController* controller =
base::mac::ObjCCast<AppController>([NSApp delegate]); base::mac::ObjCCast<AppController>([NSApp delegate]);
Method get_url = [controller getUrl:AppleEventToOpenUrl(url) withReply:nullptr];
class_getInstanceMethod([controller class], @selector(getUrl:withReply:));
ASSERT_TRUE(get_url);
NSAppleEventDescriptor* shortcut_event = AppleEventToOpenUrl(url);
method_invoke(controller, get_url, shortcut_event, NULL);
} }
void RunClosureWhenProfileInitialized(const base::Closure& closure, void RunClosureWhenProfileInitialized(const base::Closure& closure,
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
namespace { namespace {
IMP g_original_populatemenu_implementation = nullptr; base::mac::ScopedObjCClassSwizzler* g_populatemenu_swizzler = nullptr;
// |g_filtered_entries_array| is only set during testing (see // |g_filtered_entries_array| is only set during testing (see
// +[ChromeSwizzleServicesMenuUpdater storeFilteredEntriesForTestingInArray:]). // +[ChromeSwizzleServicesMenuUpdater storeFilteredEntriesForTestingInArray:]).
...@@ -98,8 +98,8 @@ NSMenuItem* GetMenuItemByID(ui::MenuModel* model, ...@@ -98,8 +98,8 @@ NSMenuItem* GetMenuItemByID(ui::MenuModel* model,
} }
// Pass the filtered array along to the _NSServicesMenuUpdater. // Pass the filtered array along to the _NSServicesMenuUpdater.
g_original_populatemenu_implementation(self, _cmd, menu, remainingEntries, g_populatemenu_swizzler->InvokeOriginal<void, NSMenu*, NSArray*, BOOL>(
display); self, _cmd, menu, remainingEntries, display);
} }
+ (void)storeFilteredEntriesForTestingInArray:(NSMutableArray*)array { + (void)storeFilteredEntriesForTestingInArray:(NSMutableArray*)array {
...@@ -145,8 +145,7 @@ NSMenuItem* GetMenuItemByID(ui::MenuModel* model, ...@@ -145,8 +145,7 @@ NSMenuItem* GetMenuItemByID(ui::MenuModel* model,
Class swizzleClass = [ChromeSwizzleServicesMenuUpdater class]; Class swizzleClass = [ChromeSwizzleServicesMenuUpdater class];
static base::NoDestructor<base::mac::ScopedObjCClassSwizzler> static base::NoDestructor<base::mac::ScopedObjCClassSwizzler>
servicesMenuFilter(targetClass, swizzleClass, targetSelector); servicesMenuFilter(targetClass, swizzleClass, targetSelector);
g_original_populatemenu_implementation = g_populatemenu_swizzler = servicesMenuFilter.get();
servicesMenuFilter->GetOriginalImplementation();
}); });
} }
......
...@@ -29,7 +29,9 @@ class SendGlobalKeyEventsHelper { ...@@ -29,7 +29,9 @@ class SendGlobalKeyEventsHelper {
// Callback for MockCrApplication. // Callback for MockCrApplication.
void ObserveSendEvent(NSEvent* event); 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); void SendGlobalKeyEventsAndWait(int key_code, int modifier_flags);
...@@ -39,7 +41,6 @@ class SendGlobalKeyEventsHelper { ...@@ -39,7 +41,6 @@ class SendGlobalKeyEventsHelper {
bool key_down); bool key_down);
std::unique_ptr<base::mac::ScopedObjCClassSwizzler> scoped_swizzler_; std::unique_ptr<base::mac::ScopedObjCClassSwizzler> scoped_swizzler_;
IMP original_send_event_ = nullptr;
base::ScopedCFTypeRef<CGEventSourceRef> event_source_; base::ScopedCFTypeRef<CGEventSourceRef> event_source_;
CGEventTapLocation event_tap_location_; CGEventTapLocation event_tap_location_;
base::RunLoop run_loop_; base::RunLoop run_loop_;
...@@ -62,7 +63,7 @@ SendGlobalKeyEventsHelper* g_global_key_events_helper = nullptr; ...@@ -62,7 +63,7 @@ SendGlobalKeyEventsHelper* g_global_key_events_helper = nullptr;
- (void)sendEvent:(NSEvent*)event { - (void)sendEvent:(NSEvent*)event {
DCHECK(g_global_key_events_helper); DCHECK(g_global_key_events_helper);
g_global_key_events_helper->ObserveSendEvent(event); 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 @end
...@@ -78,7 +79,6 @@ SendGlobalKeyEventsHelper::SendGlobalKeyEventsHelper() ...@@ -78,7 +79,6 @@ SendGlobalKeyEventsHelper::SendGlobalKeyEventsHelper()
scoped_swizzler_ = std::make_unique<base::mac::ScopedObjCClassSwizzler>( scoped_swizzler_ = std::make_unique<base::mac::ScopedObjCClassSwizzler>(
[BrowserCrApplication class], [MockCrApplication class], [BrowserCrApplication class], [MockCrApplication class],
@selector(sendEvent:)); @selector(sendEvent:));
original_send_event_ = scoped_swizzler_->GetOriginalImplementation();
} }
SendGlobalKeyEventsHelper::~SendGlobalKeyEventsHelper() { SendGlobalKeyEventsHelper::~SendGlobalKeyEventsHelper() {
......
...@@ -163,7 +163,7 @@ void GetStringFromRangeForRenderWidget( ...@@ -163,7 +163,7 @@ void GetStringFromRangeForRenderWidget(
- (void)didAddSubview:(NSView*)view { - (void)didAddSubview:(NSView*)view {
content::RenderWidgetHostViewCocoaObserver::GetSwizzler( content::RenderWidgetHostViewCocoaObserver::GetSwizzler(
content::RenderWidgetHostViewCocoaObserver::kDidAddSubview) content::RenderWidgetHostViewCocoaObserver::kDidAddSubview)
->GetOriginalImplementation()(self, _cmd, view); ->InvokeOriginal<void, NSView*>(self, _cmd, view);
content::RenderWidgetHostViewMac* rwhv_mac = content::RenderWidgetHostViewMac* rwhv_mac =
content::GetRenderWidgetHostViewMac(self); content::GetRenderWidgetHostViewMac(self);
...@@ -206,7 +206,8 @@ void GetStringFromRangeForRenderWidget( ...@@ -206,7 +206,8 @@ void GetStringFromRangeForRenderWidget(
content::RenderWidgetHostViewCocoaObserver::GetSwizzler( content::RenderWidgetHostViewCocoaObserver::GetSwizzler(
content::RenderWidgetHostViewCocoaObserver:: content::RenderWidgetHostViewCocoaObserver::
kShowDefinitionForAttributedString) kShowDefinitionForAttributedString)
->GetOriginalImplementation()(self, _cmd, attrString, textBaselineOrigin); ->InvokeOriginal<void, NSAttributedString*, NSPoint>(
self, _cmd, attrString, textBaselineOrigin);
auto* rwhv_mac = content::GetRenderWidgetHostViewMac(self); auto* rwhv_mac = content::GetRenderWidgetHostViewMac(self);
......
...@@ -14,7 +14,7 @@ using base::mac::ScopedObjCClassSwizzler; ...@@ -14,7 +14,7 @@ using base::mac::ScopedObjCClassSwizzler;
namespace { namespace {
NSWindow* g_fake_focused_window = nil; NSWindow* g_fake_focused_window = nil;
IMP g_order_out_impl_ = nullptr; base::mac::ScopedObjCClassSwizzler* g_order_out_swizzler = nullptr;
void SetFocus(NSWindow* window) { void SetFocus(NSWindow* window) {
g_fake_focused_window = window; g_fake_focused_window = window;
...@@ -74,7 +74,7 @@ void ClearFocus() { ...@@ -74,7 +74,7 @@ void ClearFocus() {
NSWindow* selfAsWindow = base::mac::ObjCCastStrict<NSWindow>(self); NSWindow* selfAsWindow = base::mac::ObjCCastStrict<NSWindow>(self);
if (selfAsWindow == g_fake_focused_window) if (selfAsWindow == g_fake_focused_window)
ClearFocus(); ClearFocus();
g_order_out_impl_(self, _cmd, sender); g_order_out_swizzler->InvokeOriginal<void, id>(self, _cmd, sender);
} }
- (void)resignKeyWindow { - (void)resignKeyWindow {
...@@ -117,10 +117,11 @@ ScopedFakeNSWindowFocus::ScopedFakeNSWindowFocus() ...@@ -117,10 +117,11 @@ ScopedFakeNSWindowFocus::ScopedFakeNSWindowFocus()
new ScopedObjCClassSwizzler([NSWindow class], new ScopedObjCClassSwizzler([NSWindow class],
[FakeNSWindowFocusDonor class], [FakeNSWindowFocusDonor class],
@selector(orderOut:))) { @selector(orderOut:))) {
g_order_out_impl_ = order_out_swizzler_->GetOriginalImplementation(); g_order_out_swizzler = order_out_swizzler_.get();
} }
ScopedFakeNSWindowFocus::~ScopedFakeNSWindowFocus() { ScopedFakeNSWindowFocus::~ScopedFakeNSWindowFocus() {
g_order_out_swizzler = nullptr;
ClearFocus(); ClearFocus();
} }
......
...@@ -61,14 +61,14 @@ class ScopedFakeNSWindowFullscreen::Impl { ...@@ -61,14 +61,14 @@ class ScopedFakeNSWindowFullscreen::Impl {
} }
} }
IMP SetStyleMaskImplementation() { void OriginalSetStyleMask(id receiver, SEL selector, NSUInteger mask) {
return set_style_mask_swizzler_.GetOriginalImplementation(); return set_style_mask_swizzler_.InvokeOriginal<void, NSUInteger>(
receiver, selector, mask);
} }
NSUInteger StyleMaskForWindow(NSWindow* window) { NSUInteger StyleMaskForWindow(NSWindow* window) {
NSUInteger actual_style_mask = reinterpret_cast<NSUInteger>( auto actual_style_mask = style_mask_swizzler_.InvokeOriginal<NSUInteger>(
style_mask_swizzler_.GetOriginalImplementation()(window, window, @selector(styleMask));
@selector(styleMask)));
if (window_ != window || !style_as_fullscreen_) if (window_ != window || !style_as_fullscreen_)
return actual_style_mask; return actual_style_mask;
...@@ -233,7 +233,7 @@ void ScopedFakeNSWindowFullscreen::FinishTransition() { ...@@ -233,7 +233,7 @@ void ScopedFakeNSWindowFullscreen::FinishTransition() {
NOTREACHED() << "Can't set NSFullScreenWindowMask while faking fullscreen."; NOTREACHED() << "Can't set NSFullScreenWindowMask while faking fullscreen.";
} }
newMask &= ~NSFullScreenWindowMask; newMask &= ~NSFullScreenWindowMask;
g_fake_fullscreen_impl->SetStyleMaskImplementation()(self, _cmd, newMask); g_fake_fullscreen_impl->OriginalSetStyleMask(self, _cmd, newMask);
} }
@end @end
...@@ -252,8 +252,8 @@ class EventGeneratorDelegateMac : public ui::EventTarget, ...@@ -252,8 +252,8 @@ class EventGeneratorDelegateMac : public ui::EventTarget,
static EventGeneratorDelegateMac* instance() { return instance_; } static EventGeneratorDelegateMac* instance() { return instance_; }
IMP CurrentEventMethod() { NSEvent* OriginalCurrentEvent(id receiver, SEL selector) {
return swizzle_current_event_->GetOriginalImplementation(); return swizzle_current_event_->InvokeOriginal<NSEvent*>(receiver, selector);
} }
NSWindow* window() { return window_.get(); } NSWindow* window() { return window_.get(); }
...@@ -634,8 +634,8 @@ CreateEventGeneratorDelegateMac(ui::test::EventGenerator* owner, ...@@ -634,8 +634,8 @@ CreateEventGeneratorDelegateMac(ui::test::EventGenerator* owner,
return g_current_event; return g_current_event;
// Find the original implementation and invoke it. // Find the original implementation and invoke it.
IMP original = EventGeneratorDelegateMac::instance()->CurrentEventMethod(); return EventGeneratorDelegateMac::instance()->OriginalCurrentEvent(self,
return original(self, _cmd); _cmd);
} }
@end @end
...@@ -1139,8 +1139,8 @@ class ScopedSwizzleWaiter { ...@@ -1139,8 +1139,8 @@ class ScopedSwizzleWaiter {
~ScopedSwizzleWaiter() { instance_ = nullptr; } ~ScopedSwizzleWaiter() { instance_ = nullptr; }
static IMP GetMethodAndMarkCalled() { static void OriginalSetWindowStateForEnd(id receiver, SEL method) {
return instance_->GetMethodInternal(); return instance_->CallMethodInternal(receiver, method);
} }
void WaitForMethod() { void WaitForMethod() {
...@@ -1158,12 +1158,12 @@ class ScopedSwizzleWaiter { ...@@ -1158,12 +1158,12 @@ class ScopedSwizzleWaiter {
bool method_called() const { return method_called_; } bool method_called() const { return method_called_; }
private: private:
IMP GetMethodInternal() { void CallMethodInternal(id receiver, SEL selector) {
DCHECK(!method_called_); DCHECK(!method_called_);
method_called_ = true; method_called_ = true;
if (run_loop_) if (run_loop_)
run_loop_->Quit(); run_loop_->Quit();
return swizzler_.GetOriginalImplementation(); swizzler_.InvokeOriginal<void>(receiver, selector);
} }
static ScopedSwizzleWaiter* instance_; static ScopedSwizzleWaiter* instance_;
...@@ -2475,7 +2475,7 @@ TEST_F(NativeWidgetMacTest, InitCallback) { ...@@ -2475,7 +2475,7 @@ TEST_F(NativeWidgetMacTest, InitCallback) {
@implementation TestStopAnimationWaiter @implementation TestStopAnimationWaiter
- (void)setWindowStateForEnd { - (void)setWindowStateForEnd {
views::test::ScopedSwizzleWaiter::GetMethodAndMarkCalled()(self, _cmd); views::test::ScopedSwizzleWaiter::OriginalSetWindowStateForEnd(self, _cmd);
} }
@end @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