123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- // Copyright 2019 Dolphin Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #include "MacUpdater/ViewController.h"
- #include "UpdaterCommon/Platform.h"
- #include "UpdaterCommon/UI.h"
- #include "UpdaterCommon/UpdaterCommon.h"
- #include <Cocoa/Cocoa.h>
- #include <unistd.h>
- #include <functional>
- // When we call from the main thread, we are not allowed to use
- // dispatch_sync(dispatch_get_main_queue() as it will cause crashes) To prevent this check if we're
- // already on the main thread first
- void run_on_main(std::function<void()> fnc)
- {
- if (![NSThread isMainThread])
- {
- dispatch_sync(dispatch_get_main_queue(), ^{
- fnc();
- });
- }
- else
- {
- fnc();
- }
- }
- NSWindow* GetWindow()
- {
- return [[[NSApplication sharedApplication] windows] objectAtIndex:0];
- }
- ViewController* GetView()
- {
- return (ViewController*)GetWindow().contentViewController;
- }
- void UI::Error(const std::string& text)
- {
- run_on_main([&] {
- NSAlert* alert = [[[NSAlert alloc] init] autorelease];
- [alert setMessageText:@"Fatal error"];
- [alert setInformativeText:[NSString stringWithCString:text.c_str()
- encoding:NSUTF8StringEncoding]];
- [alert setAlertStyle:NSAlertStyleCritical];
- [alert beginSheetModalForWindow:GetWindow()
- completionHandler:^(NSModalResponse) {
- [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
- }];
- });
- }
- void UI::SetVisible(bool visible)
- {
- run_on_main([&] {
- if (visible)
- {
- [NSApp unhide:nil];
- [NSApp activateIgnoringOtherApps:YES];
- }
- else
- {
- [NSApp hide:nil];
- }
- });
- }
- void UI::SetDescription(const std::string& text)
- {
- run_on_main([&] {
- [GetView() SetDescription:[NSString stringWithCString:text.c_str()
- encoding:NSUTF8StringEncoding]];
- });
- }
- void UI::SetTotalMarquee(bool marquee)
- {
- run_on_main([marquee] { [GetView() SetTotalMarquee:marquee]; });
- }
- void UI::SetCurrentMarquee(bool marquee)
- {
- run_on_main([&] { [GetView() SetCurrentMarquee:marquee]; });
- }
- void UI::ResetTotalProgress()
- {
- run_on_main([] { SetTotalProgress(0, 1); });
- }
- void UI::ResetCurrentProgress()
- {
- run_on_main([] { SetCurrentProgress(0, 1); });
- }
- void UI::SetCurrentProgress(int current, int total)
- {
- run_on_main([&] { [GetView() SetCurrentProgress:(double)current total:(double)total]; });
- }
- void UI::SetTotalProgress(int current, int total)
- {
- run_on_main([&] { [GetView() SetTotalProgress:(double)current total:(double)total]; });
- }
- void UI::Sleep(int seconds)
- {
- [NSThread sleepForTimeInterval:static_cast<float>(seconds)];
- }
- void UI::WaitForPID(u32 pid)
- {
- for (int res = kill(pid, 0); res == 0 || (res < 0 && errno == EPERM); res = kill(pid, 0))
- {
- UI::Sleep(1);
- }
- }
- void UI::LaunchApplication(std::string path)
- {
- [[NSWorkspace sharedWorkspace]
- launchApplication:[NSString stringWithCString:path.c_str()
- encoding:[NSString defaultCStringEncoding]]];
- }
- void UI::Stop()
- {
- run_on_main([] { [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; });
- }
- // Stub. Only needed on Windows
- void UI::Init()
- {
- }
- // test-updater.py only works on Windows.
- bool UI::IsTestMode()
- {
- return false;
- }
- bool Platform::VersionCheck(const std::vector<TodoList::UpdateOp>& to_update,
- const std::string& install_base_path, const std::string& temp_dir)
- {
- const auto op_it = std::find_if(to_update.cbegin(), to_update.cend(), [&](const auto& op) {
- return op.filename == "Dolphin.app/Contents/Info.plist";
- });
- if (op_it == to_update.cend())
- return true;
- const auto op = *op_it;
- std::string plist_path = temp_dir + "/" + HexEncode(op.new_hash.data(), op.new_hash.size());
- NSData* data = [NSData dataWithContentsOfFile:[NSString stringWithCString:plist_path.c_str()]];
- if (!data)
- {
- LogToFile("Failed to read %s, skipping platform version check.\n", plist_path.c_str());
- return true;
- }
- NSError* error = nil;
- NSDictionary* info_dict =
- [NSPropertyListSerialization propertyListWithData:data
- options:NSPropertyListImmutable
- format:nil
- error:&error];
- if (error)
- {
- LogToFile("Failed to parse %s, skipping platform version check.\n", plist_path.c_str());
- return true;
- }
- NSString* min_version_str = info_dict[@"LSMinimumSystemVersion"];
- if (!min_version_str)
- {
- LogToFile("LSMinimumSystemVersion key missing, skipping platform version check.\n");
- return true;
- }
- NSArray* components = [min_version_str componentsSeparatedByString:@"."];
- NSOperatingSystemVersion next_version{
- [components[0] integerValue], [components[1] integerValue], [components[2] integerValue]};
- LogToFile("Platform version check: next_version=%ld.%ld.%ld\n", (long)next_version.majorVersion,
- (long)next_version.minorVersion, (long)next_version.patchVersion);
- if (![[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:next_version])
- {
- UI::Error("Please update macOS in order to update Dolphin.");
- return false;
- }
- return true;
- }
|