Commit 7ee639e9 authored by Avi Drissman's avatar Avi Drissman Committed by Commit Bot

Add the ability to request Rosetta installation

Bug: 1145672, 1145792, 1142017
Change-Id: Idfb5ddc8f64a4f55814c5cc67d6852ca2cf3af3e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2520521
Commit-Queue: Avi Drissman <avi@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#824970}
parent cacb2ee2
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <vector> #include <vector>
#include "base/base_export.h" #include "base/base_export.h"
#include "base/callback.h"
#include "base/strings/string16.h"
#include "build/build_config.h" #include "build/build_config.h"
namespace base { namespace base {
...@@ -28,6 +30,18 @@ bool ProcessIsTranslated(); ...@@ -28,6 +30,18 @@ bool ProcessIsTranslated();
// Returns true if Rosetta is installed and available to translate x86_64 code. // Returns true if Rosetta is installed and available to translate x86_64 code.
BASE_EXPORT bool IsRosettaInstalled(); BASE_EXPORT bool IsRosettaInstalled();
// Prompt the user to allow for the installation of Rosetta. `callback` is
// called with true if Rosetta is already installed, or if the user consented to
// installation and Rosetta was installed. It's called with false otherwise. The
// UI is presented to the user in a dialog with the `title_text` and
// `body_text`. Its thread-safety is not known; call it from the main thread and
// the callback will happen on the main thread as well. This can only be called
// once per run of Chromium to avoid confusing the user; it will call the
// callback with false if called subsequent times.
BASE_EXPORT void RequestRosettaInstallation(const string16& title_text,
const string16& body_text,
OnceCallback<void(bool)> callback);
#endif // ARCH_CPU_ARM64 #endif // ARCH_CPU_ARM64
// Requests an ahead-of-time translation of the binaries with paths given in // Requests an ahead-of-time translation of the binaries with paths given in
......
...@@ -4,14 +4,22 @@ ...@@ -4,14 +4,22 @@
#include "base/mac/rosetta.h" #include "base/mac/rosetta.h"
#include <AppKit/AppKit.h>
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <mach/machine.h> #include <mach/machine.h>
#include <string.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/types.h> #include <sys/types.h>
#include <utility>
#include "base/check.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/mac/scoped_nsobject.h"
#include "base/mac/sdk_forward_declarations.h" #include "base/mac/sdk_forward_declarations.h"
#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/scoped_blocking_call.h" #include "base/threading/scoped_blocking_call.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -44,6 +52,93 @@ bool IsRosettaInstalled() { ...@@ -44,6 +52,93 @@ bool IsRosettaInstalled() {
#pragma clang diagnostic pop #pragma clang diagnostic pop
} }
void RequestRosettaInstallation(const string16& title_text,
const string16& body_text,
OnceCallback<void(bool)> callback) {
DCHECK([NSThread isMainThread]);
if (IsRosettaInstalled()) {
std::move(callback).Run(true);
return;
}
static bool been_there_done_that = false;
if (been_there_done_that) {
std::move(callback).Run(false);
return;
}
been_there_done_that = true;
@autoreleasepool {
static const NoDestructor<scoped_nsobject<NSBundle>> bundle([]() {
scoped_nsobject<NSBundle> bundle(
[[NSBundle alloc] initWithPath:@"/System/Library/PrivateFrameworks/"
@"OAHSoftwareUpdate.framework"]);
if (![bundle load])
return scoped_nsobject<NSBundle>();
return bundle;
}());
if (!bundle.get()) {
std::move(callback).Run(false);
return;
}
// The method being called is:
//
// - (void)[OAHSoftwareUpdateController
// startUpdateWithOptions:(NSDictionary*)options
// withHostWindow:(NSWindow*)window
// completion:(void (^)(BOOL))block]
SEL selector = @selector(startUpdateWithOptions:withHostWindow:completion:);
scoped_nsobject<NSObject> controller(
[[NSClassFromString(@"OAHSoftwareUpdateController") alloc] init]);
NSMethodSignature* signature =
[controller methodSignatureForSelector:selector];
if (!signature) {
std::move(callback).Run(false);
return;
}
if (strcmp(signature.methodReturnType, "v") != 0 ||
signature.numberOfArguments != 5 ||
strcmp([signature getArgumentTypeAtIndex:0], "@") != 0 ||
strcmp([signature getArgumentTypeAtIndex:1], ":") != 0 ||
strcmp([signature getArgumentTypeAtIndex:2], "@") != 0 ||
strcmp([signature getArgumentTypeAtIndex:3], "@") != 0 ||
strcmp([signature getArgumentTypeAtIndex:4], "@?") != 0) {
std::move(callback).Run(false);
return;
}
NSInvocation* invocation =
[NSInvocation invocationWithMethodSignature:signature];
__block NSObject* block_controller = [controller.get() retain];
invocation.target = block_controller;
invocation.selector = selector;
NSDictionary* options = @{
@"TitleText" : SysUTF16ToNSString(title_text),
@"BodyText" : SysUTF16ToNSString(body_text)
};
[invocation setArgument:&options atIndex:2];
NSWindow* window = nil;
[invocation setArgument:&window atIndex:3];
__block OnceCallback<void(bool)> block_callback = std::move(callback);
auto completion = ^(BOOL success) {
[controller release];
std::move(block_callback).Run(success);
};
[invocation setArgument:&completion atIndex:4];
[invocation invoke];
}
}
#endif // ARCH_CPU_ARM64 #endif // ARCH_CPU_ARM64
bool RequestRosettaAheadOfTimeTranslation( bool RequestRosettaAheadOfTimeTranslation(
...@@ -76,8 +171,7 @@ bool RequestRosettaAheadOfTimeTranslation( ...@@ -76,8 +171,7 @@ bool RequestRosettaAheadOfTimeTranslation(
path_strs.push_back(paths.back().c_str()); path_strs.push_back(paths.back().c_str());
} }
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
base::BlockingType::MAY_BLOCK);
return oah_translate_binaries(path_strs.data(), path_strs.size()); return oah_translate_binaries(path_strs.data(), path_strs.size());
} }
......
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