Skip to content

Commit faa21a7

Browse files
authored
fix: MAS rejection for private APIs (electron#49391)
1 parent 5bd2938 commit faa21a7

File tree

1 file changed

+290
-8
lines changed

1 file changed

+290
-8
lines changed

patches/chromium/mas_avoid_private_macos_api_usage.patch.patch

Lines changed: 290 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ Subject: mas: avoid private macOS API usage
1616
* NSNextStepFrame
1717
* NSThemeFrame
1818
* NSTextInputReplacementRangeAttributeName
19+
* _toolbarView
20+
* _menuImpl
21+
* _removeFromGroups:
22+
* _isConsideredOpenForPersistentState
23+
* _boundsIfOpen
24+
* _resizeDirectionForMouseLocation:
25+
* NSAppendToKillRing
26+
* kCFBundleNumericVersionKey
27+
* __NSNewKillRingSequence
28+
* __NSInitializeKillRing
29+
* NSYankFromKillRing
30+
* NSSetKillRingToYankedState
1931
* NSAccessibilityRemoteUIElement is unnecessary for Electron's use-case. We use it
2032
for progressive web apps (where the AXTree is in the browser process, but macOS
2133
needs to think it's coming from the PWA process). I think it can just be chopped
@@ -80,6 +92,40 @@ index 4bf9a3c27e05c6635b2beb8e880b5b43dbed61b5..f328fbb49c45991f44a9c75325491d08
8092
+#endif
8193

8294
} // namespace base
95+
diff --git a/base/mac/info_plist_data.mm b/base/mac/info_plist_data.mm
96+
index 419a051968c58ae5a761708e4d942e8975c70852..a77032dd43f5fcbe29c54b622b34607fba09d350 100644
97+
--- a/base/mac/info_plist_data.mm
98+
+++ b/base/mac/info_plist_data.mm
99+
@@ -11,15 +11,19 @@
100+
#include "base/apple/bundle_locations.h"
101+
#include "base/apple/foundation_util.h"
102+
#include "base/containers/span.h"
103+
+#include "electron/mas.h"
104+
105+
+#if !IS_MAS_BUILD()
106+
extern "C" {
107+
// Key used within CoreFoundation for loaded Info plists
108+
extern const CFStringRef _kCFBundleNumericVersionKey;
109+
}
110+
+#endif
111+
112+
namespace base::mac {
113+
114+
std::vector<uint8_t> OuterBundleCachedInfoPlistData() {
115+
+#if !IS_MAS_BUILD()
116+
// NSBundle's info dictionary is used to ensure that any changes to Info.plist
117+
// on disk due to pending updates do not result in a version of the data being
118+
// used that doesn't match the code signature of the running app.
119+
@@ -43,6 +47,9 @@
120+
error:nullptr];
121+
base::span<const uint8_t> span = apple::NSDataToSpan(data);
122+
return {span.begin(), span.end()};
123+
+#else
124+
+ return {};
125+
+#endif
126+
}
127+
128+
} // namespace base::mac
83129
diff --git a/base/process/launch_mac.cc b/base/process/launch_mac.cc
84130
index b63d58da9837ba4d1e4aff8f24f2cd977c5ed02d..8387fd7d2bcf8951b6cc024829c16d970799190c 100644
85131
--- a/base/process/launch_mac.cc
@@ -230,6 +276,25 @@ index ba813851fde2660c21f99248a124161d2ac2ca07..c34f920e4a592b6798f5307c726bc34e
230276
"//mojo/public/cpp/bindings",
231277
"//net",
232278
"//ui/accelerated_widget_mac",
279+
diff --git a/components/remote_cocoa/app_shim/NSToolbar+Private.mm b/components/remote_cocoa/app_shim/NSToolbar+Private.mm
280+
index 5c6f4c37205de6d7cfb91c837ad4586473cf2fdb..551dc7a0e71711eee9d5176a33b345b8b8b276fb 100644
281+
--- a/components/remote_cocoa/app_shim/NSToolbar+Private.mm
282+
+++ b/components/remote_cocoa/app_shim/NSToolbar+Private.mm
283+
@@ -4,6 +4,9 @@
284+
285+
#import "components/remote_cocoa/app_shim/NSToolbar+Private.h"
286+
287+
+#include "electron/mas.h"
288+
+
289+
+#if !IS_MAS_BUILD()
290+
// Access the private view that backs the toolbar.
291+
// TODO(http://crbug.com/40261565): Remove when FB12010731 is fixed in AppKit.
292+
@interface NSToolbar (ToolbarView)
293+
@@ -18,3 +21,4 @@ - (NSView *)privateToolbarView {
294+
: nil;
295+
}
296+
@end
297+
+#endif
233298
diff --git a/components/remote_cocoa/app_shim/application_bridge.mm b/components/remote_cocoa/app_shim/application_bridge.mm
234299
index d5afd4be1ef4ac3fd1cfa7c09c667bc87b9a6b3a..4f005f2fe24ecfe1962fc64782fb7187161cbd7a 100644
235300
--- a/components/remote_cocoa/app_shim/application_bridge.mm
@@ -320,6 +385,62 @@ index f7200edbe6059ac6d7ade0672852b52da7642a71..0cc5da96411b46eb39d0c01dfec59cb5
320385
}
321386

322387
@end
388+
diff --git a/components/remote_cocoa/app_shim/menu_controller_cocoa_delegate_impl.mm b/components/remote_cocoa/app_shim/menu_controller_cocoa_delegate_impl.mm
389+
index 5dd3ae5dff160834524c013594f76f59ad7e2fdd..356d677b9e6addeeb60af6b4e2d63125bc4f51c4 100644
390+
--- a/components/remote_cocoa/app_shim/menu_controller_cocoa_delegate_impl.mm
391+
+++ b/components/remote_cocoa/app_shim/menu_controller_cocoa_delegate_impl.mm
392+
@@ -8,6 +8,7 @@
393+
#include "base/apple/foundation_util.h"
394+
#include "base/logging.h"
395+
#import "base/message_loop/message_pump_apple.h"
396+
+#import "electron/mas.h"
397+
#import "skia/ext/skia_utils_mac.h"
398+
#import "ui/base/cocoa/cocoa_base_utils.h"
399+
#include "ui/base/interaction/element_tracker_mac.h"
400+
@@ -111,6 +112,7 @@ - (void)highlightItemAtIndex:(NSInteger)index;
401+
402+
@interface NSMenu (Impl)
403+
404+
+#if !IS_MAS_BUILD()
405+
// Returns the impl. (If called on macOS 14 this would return a subclass of
406+
// NSCocoaMenuImpl, but private API use is not needed on macOS 14.)
407+
- (id<CrNSCarbonMenuImpl>)_menuImpl;
408+
@@ -119,6 +121,7 @@ @interface NSMenu (Impl)
409+
// on both Carbon and Cocoa impls, but always (incorrectly) returns a zero
410+
// origin with the Cocoa impl. Therefore, do not use with macOS 14 or later.
411+
- (CGRect)_boundsIfOpen;
412+
+#endif
413+
414+
@end
415+
416+
@@ -239,6 +242,7 @@ - (void)controllerWillAddMenu:(NSMenu*)menu fromModel:(ui::MenuModel*)model {
417+
}
418+
menuShown = true;
419+
420+
+#if !IS_MAS_BUILD()
421+
if (alertedIndex.has_value()) {
422+
const auto index = base::checked_cast<NSInteger>(alertedIndex.value());
423+
if (@available(macOS 14.0, *)) {
424+
@@ -247,6 +251,7 @@ - (void)controllerWillAddMenu:(NSMenu*)menu fromModel:(ui::MenuModel*)model {
425+
[strongMenu._menuImpl highlightItemAtIndex:index];
426+
}
427+
}
428+
+#endif
429+
430+
if (@available(macOS 14.0, *)) {
431+
for (auto [elementId, index] : elementIds) {
432+
@@ -267,7 +272,11 @@ - (void)controllerWillAddMenu:(NSMenu*)menu fromModel:(ui::MenuModel*)model {
433+
dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC),
434+
dispatch_get_main_queue(), ^{
435+
gfx::Rect bounds =
436+
+#if !IS_MAS_BUILD()
437+
gfx::ScreenRectFromNSRect(strongMenu._boundsIfOpen);
438+
+#else
439+
+ gfx::ScreenRectFromNSRect(NSMakeRect(0, 0, 0, 0));
440+
+#endif
441+
for (auto [elementId, index] : elementIds) {
442+
ui::ElementTrackerMac::GetInstance()->NotifyMenuItemShown(
443+
strongMenu, elementId, bounds);
323444
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.mm
324445
index 3a815ebf505bd95fa7f6b61ba433d98fbfe20225..149de0175c2ec0e41e3ba40caad7019ca87386d6 100644
325446
--- a/components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.mm
@@ -384,7 +505,7 @@ index 020050de162705651b4eb8378880cd4eb017d46c..2d3554861a570271d6f9b9a2c8b1de53
384505
// The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that
385506
// can only be accomplished by overriding methods.
386507
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
387-
index a474e70cf3c10405b6f94f129f5a7312bb81fd73..9463bd647a4d47ff3241579255966f5e4409941a 100644
508+
index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6b192912c 100644
388509
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
389510
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
390511
@@ -21,6 +21,7 @@
@@ -395,7 +516,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..9463bd647a4d47ff3241579255966f5e
395516
#include "ui/accessibility/platform/ax_platform_node.h"
396517
#import "ui/base/cocoa/user_interface_item_command_handler.h"
397518
#import "ui/base/cocoa/window_size_constants.h"
398-
@@ -108,14 +109,18 @@ void OrderChildWindow(NSWindow* child_window,
519+
@@ -108,20 +109,24 @@ void OrderChildWindow(NSWindow* child_window,
399520

400521
} // namespace
401522

@@ -410,11 +531,27 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..9463bd647a4d47ff3241579255966f5e
410531
@interface NSWindow (Private)
411532
+#if !IS_MAS_BUILD()
412533
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle;
413-
+#endif
414-
- (BOOL)hasKeyAppearance;
534+
-- (BOOL)hasKeyAppearance;
415535
- (long long)_resizeDirectionForMouseLocation:(CGPoint)location;
416536
- (BOOL)_isConsideredOpenForPersistentState;
417-
@@ -165,6 +170,8 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event {
537+
- (void)_zoomToScreenEdge:(NSUInteger)edge;
538+
- (void)_removeFromGroups:(NSWindow*)window;
539+
- (BOOL)_isNonactivatingPanel;
540+
+#endif
541+
+- (BOOL)hasKeyAppearance;
542+
@end
543+
544+
struct NSEdgeAndCornerThicknesses {
545+
@@ -158,13 +163,17 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
546+
@implementation NSView (CRFrameViewAdditions)
547+
// If a mouseDown: falls through to the frame view, turn it into a window drag.
548+
- (void)cr_mouseDownOnFrameView:(NSEvent*)event {
549+
+#if !IS_MAS_BUILD()
550+
if ([self.window _resizeDirectionForMouseLocation:event.locationInWindow] !=
551+
-1)
552+
return;
553+
+#endif
554+
[self.window performWindowDragWithEvent:event];
418555
}
419556
@end
420557

@@ -423,7 +560,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..9463bd647a4d47ff3241579255966f5e
423560
@implementation NativeWidgetMacNSWindowTitledFrame
424561
- (void)mouseDown:(NSEvent*)event {
425562
if (self.window.isMovable)
426-
@@ -192,6 +199,8 @@ - (BOOL)usesCustomDrawing {
563+
@@ -192,6 +201,8 @@ - (BOOL)usesCustomDrawing {
427564
}
428565
@end
429566

@@ -432,7 +569,23 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..9463bd647a4d47ff3241579255966f5e
432569
@implementation NativeWidgetMacNSWindow {
433570
@private
434571
CommandDispatcher* __strong _commandDispatcher;
435-
@@ -393,6 +402,8 @@ - (NSAccessibilityRole)accessibilityRole {
572+
@@ -241,6 +252,7 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
573+
// bubbles and the find bar, but these should not be movable.
574+
// Instead, let's push this up to the parent window which should be
575+
// the browser.
576+
+#if !IS_MAS_BUILD()
577+
- (void)_zoomToScreenEdge:(NSUInteger)edge {
578+
if (self.parentWindow) {
579+
[self.parentWindow _zoomToScreenEdge:edge];
580+
@@ -248,6 +260,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
581+
[super _zoomToScreenEdge:edge];
582+
}
583+
}
584+
+#endif
585+
586+
// This override helps diagnose lifetime issues in crash stacktraces by
587+
// inserting a symbol on NativeWidgetMacNSWindow and should be kept even if it
588+
@@ -393,6 +406,8 @@ - (NSAccessibilityRole)accessibilityRole {
436589

437590
// NSWindow overrides.
438591

@@ -441,7 +594,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..9463bd647a4d47ff3241579255966f5e
441594
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
442595
if (windowStyle & NSWindowStyleMaskTitled) {
443596
if (Class customFrame = [NativeWidgetMacNSWindowTitledFrame class])
444-
@@ -404,6 +415,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
597+
@@ -404,6 +419,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
445598
return [super frameViewClassForStyleMask:windowStyle];
446599
}
447600

@@ -450,6 +603,65 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..9463bd647a4d47ff3241579255966f5e
450603
- (BOOL)_isTitleHidden {
451604
bool shouldShowWindowTitle = YES;
452605
if (_bridge)
606+
@@ -428,12 +445,14 @@ - (BOOL)_usesCustomDrawing {
607+
// if it were valid to set that style for windows, setting the window style
608+
// recalculates and re-caches a bunch of stuff, so a surgical override is the
609+
// cleanest approach.
610+
+#if !IS_MAS_BUILD()
611+
- (BOOL)_isNonactivatingPanel {
612+
if (_activationIndependence) {
613+
return YES;
614+
}
615+
return [super _isNonactivatingPanel];
616+
}
617+
+#endif
618+
619+
+ (void)_getExteriorResizeEdgeThicknesses:
620+
(NSEdgeAndCornerThicknesses*)outThicknesses
621+
@@ -687,9 +706,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
622+
}
623+
624+
- (void)saveRestorableState {
625+
+#if !IS_MAS_BUILD()
626+
if (!_bridge || ![self _isConsideredOpenForPersistentState]) {
627+
return;
628+
}
629+
+#endif
630+
631+
// Certain conditions, such as in the Speedometer 3 benchmark, can trigger a
632+
// rapid succession of calls to saveRestorableState. If there's no pending
633+
@@ -756,6 +777,7 @@ - (void)reallySaveRestorableState {
634+
// affects its restorable state changes.
635+
- (void)invalidateRestorableState {
636+
[super invalidateRestorableState];
637+
+#if !IS_MAS_BUILD()
638+
if ([self _isConsideredOpenForPersistentState]) {
639+
if (_willUpdateRestorableState)
640+
return;
641+
@@ -768,6 +790,7 @@ - (void)invalidateRestorableState {
642+
_willUpdateRestorableState = NO;
643+
[NSObject cancelPreviousPerformRequestsWithTarget:self];
644+
}
645+
+#endif
646+
}
647+
648+
// On newer SDKs, _canMiniaturize respects NSWindowStyleMaskMiniaturizable in
649+
@@ -932,6 +955,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
650+
// Since _removeFromGroups: is not documented it could go away in newer
651+
// versions of macOS. If the selector does not exist, DumpWithoutCrashing() so
652+
// we hear about the change.
653+
+#if !IS_MAS_BUILD()
654+
if (![NSWindow instancesRespondToSelector:@selector(_removeFromGroups:)]) {
655+
base::debug::DumpWithoutCrashing();
656+
return;
657+
@@ -949,6 +973,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
658+
[currentWindow _removeFromGroups:child];
659+
}
660+
}
661+
+#endif
662+
}
663+
664+
- (NSWindow*)rootWindow {
453665
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
454666
index 414874d84338ff12e707d52bc82483957d74d8ef..849da439a046aea133946572c79964858e4e7ba5 100644
455667
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -1426,6 +1638,76 @@ index 4f04476e9175bae9e89eb9ea4316bffe49a9eb91..e77615c7b26518f4930ac1b004b41317
14261638
} else {
14271639
blink_core_sources_editing += [ "kill_ring_none.cc" ]
14281640
}
1641+
diff --git a/third_party/blink/renderer/core/editing/kill_ring_mac.mm b/third_party/blink/renderer/core/editing/kill_ring_mac.mm
1642+
index 94afefcee81b87c05bf9b1199d90d3d4b5ea84a6..3e3aaea0ec6c8fad0d90a931d269af3af01ab73a 100644
1643+
--- a/third_party/blink/renderer/core/editing/kill_ring_mac.mm
1644+
+++ b/third_party/blink/renderer/core/editing/kill_ring_mac.mm
1645+
@@ -25,8 +25,11 @@
1646+
1647+
#import "third_party/blink/renderer/core/editing/kill_ring.h"
1648+
1649+
+#include "electron/mas.h"
1650+
+
1651+
namespace blink {
1652+
1653+
+#if !IS_MAS_BUILD()
1654+
extern "C" {
1655+
1656+
// Kill ring calls. Would be better to use NSKillRing.h, but that's not
1657+
@@ -39,7 +42,9 @@
1658+
void _NSNewKillRingSequence();
1659+
void _NSSetKillRingToYankedState();
1660+
}
1661+
+#endif // !IS_MAS_BUILD()
1662+
1663+
+#if !IS_MAS_BUILD()
1664+
static void InitializeKillRingIfNeeded() {
1665+
static bool initialized_kill_ring = false;
1666+
if (!initialized_kill_ring) {
1667+
@@ -47,30 +52,43 @@ static void InitializeKillRingIfNeeded() {
1668+
_NSInitializeKillRing();
1669+
}
1670+
}
1671+
+#endif // !IS_MAS_BUILD()
1672+
1673+
void KillRing::Append(const String& string) {
1674+
+#if !IS_MAS_BUILD()
1675+
InitializeKillRingIfNeeded();
1676+
_NSAppendToKillRing(string);
1677+
+#endif // !IS_MAS_BUILD()
1678+
}
1679+
1680+
void KillRing::Prepend(const String& string) {
1681+
+#if !IS_MAS_BUILD()
1682+
InitializeKillRingIfNeeded();
1683+
_NSPrependToKillRing(string);
1684+
+#endif // !IS_MAS_BUILD()
1685+
}
1686+
1687+
String KillRing::Yank() {
1688+
+#if !IS_MAS_BUILD()
1689+
InitializeKillRingIfNeeded();
1690+
return _NSYankFromKillRing();
1691+
+#else
1692+
+ return String();
1693+
+#endif // !IS_MAS_BUILD()
1694+
}
1695+
1696+
void KillRing::StartNewSequence() {
1697+
+#if !IS_MAS_BUILD()
1698+
InitializeKillRingIfNeeded();
1699+
_NSNewKillRingSequence();
1700+
+#endif // !IS_MAS_BUILD()
1701+
}
1702+
1703+
void KillRing::SetToYankedState() {
1704+
+#if !IS_MAS_BUILD()
1705+
InitializeKillRingIfNeeded();
1706+
_NSSetKillRingToYankedState();
1707+
+#endif // !IS_MAS_BUILD()
1708+
}
1709+
1710+
} // namespace blink
14291711
diff --git a/ui/accelerated_widget_mac/BUILD.gn b/ui/accelerated_widget_mac/BUILD.gn
14301712
index 0f8a6f75b7f01029adc2f5fd23559bacce19cf72..cf66c2f4f02a8e21cc83c3b7389fc5156bcd93ba 100644
14311713
--- a/ui/accelerated_widget_mac/BUILD.gn

0 commit comments

Comments
 (0)