diff --git a/src/cloud.cpp b/src/cloud.cpp index ecb5aa691..488127b3d 100644 --- a/src/cloud.cpp +++ b/src/cloud.cpp @@ -50,6 +50,9 @@ extern "C" { } #endif +bool pending_login = false; +bool pending_logout = false; + struct file_metadata_t { std::string id; @@ -99,7 +102,7 @@ struct cloud_drive_t } }; -void google_cloud_drive_init(cloud_drive_t*, std::function); +void google_cloud_drive_init(cloud_drive_t*); #define GOOGLE_CLIENT_ID "617320710875-o9ev86s5ad18bmmgb98p0dkbqlfufekr.apps.googleusercontent.com" #define GOOGLE_CLIENT_ID_WEB "617320710875-dakb2f10lgnnn3a97bgva18l83221pc3.apps.googleusercontent.com" @@ -277,13 +280,12 @@ extern "C" void em_oath_sign_in_callback(cloud_drive_t* drive, const char* refre sb_save_file_data(refresh_path.c_str(), (uint8_t*)drive->refresh_token.c_str(), drive->refresh_token.size() + 1); em_flush_fs(); - google_cloud_drive_init(drive, drive->ready_callback); + google_cloud_drive_init(drive); } else { printf("[cloud] refresh token or access token is null\n"); drive->ready_callback(nullptr); - delete drive; } } #endif @@ -717,20 +719,20 @@ bool google_check_username_exists(cloud_drive_t* drive) return false; } -void google_get_user_data(cloud_drive_t* drive, std::function callback) +void google_get_user_data(cloud_drive_t* drive) { bool avatar_exists = google_check_avatar_exists(drive); bool username_exists = google_check_username_exists(drive); if (avatar_exists && username_exists) { - callback(drive); + drive->ready_callback(drive); return; } drive->inc(); https_request(http_request_e::GET, "https://www.googleapis.com/drive/v3/about?fields=user", "", {{"Authorization", "Bearer " + drive->access_token}}, - [drive, avatar_exists, callback](const std::vector& data) { + [drive, avatar_exists](const std::vector& data) { std::string path = drive->save_directory + "cloud_username.txt"; nlohmann::json json = nlohmann::json::parse(data); if (json.find("error") != json.end()) @@ -738,6 +740,7 @@ void google_get_user_data(cloud_drive_t* drive, std::functiondec(); + drive->ready_callback(nullptr); return; } @@ -749,18 +752,19 @@ void google_get_user_data(cloud_drive_t* drive, std::functioninc(); std::string url = json["user"]["photoLink"]; https_request(http_request_e::GET, url, "", {}, - [drive, callback](const std::vector& data) { + [drive](const std::vector& data) { sb_save_file_data( (drive->save_directory + "profile_picture").c_str(), data.data(), data.size()); em_flush_fs(); google_check_avatar_exists(drive); - callback(drive); drive->dec(); + drive->ready_callback(drive); }); } else { printf("[cloud] failed to get username: no user in response\n"); drive->dec(); + drive->ready_callback(nullptr); return; } drive->dec(); @@ -770,17 +774,14 @@ void google_get_user_data(cloud_drive_t* drive, std::function callback) { google_cloud_drive_upload(drive, name, parent, "application/vnd.google-apps.folder", NULL, - 0, [callback](cloud_drive_t* drive) { - google_cloud_drive_get_files( - drive, [callback](cloud_drive_t* drive) { - google_get_user_data(drive, callback); - }); - }); + 0, [callback](cloud_drive_t* drive) { + callback(drive); + }); } -void google_cloud_drive_init(cloud_drive_t* drive, std::function callback) +void google_cloud_drive_init(cloud_drive_t* drive) { - google_cloud_drive_get_files(drive, [callback](cloud_drive_t* drive) { + google_cloud_drive_get_files(drive, [](cloud_drive_t* drive) { bool folders_exist; bool skyemu_folder_exists; bool save_states_folder_exists; @@ -794,18 +795,18 @@ void google_cloud_drive_init(cloud_drive_t* drive, std::functionready_callback(nullptr); return; } @@ -904,7 +905,7 @@ void cloud_drive_authenticate(cloud_drive_t* drive) sb_save_file_data(refresh_path.c_str(), (uint8_t*)drive->refresh_token.c_str(), drive->refresh_token.size() + 1); em_flush_fs(); - google_cloud_drive_init(drive, drive->ready_callback); + google_cloud_drive_init(drive); }); #ifdef SE_PLATFORM_ANDROID @@ -919,13 +920,13 @@ void cloud_drive_authenticate(cloud_drive_t* drive) { std::string error = req.get_param_value("error"); printf("[cloud] while authenticating got error: %s\n", error.c_str()); - delete drive; + drive->ready_callback(nullptr); } else { printf( "[cloud] while authenticating got response that contains neither code nor error\n"); - delete drive; + drive->ready_callback(nullptr); } }); // TODO: disallow http_server from listening to port 5000 @@ -935,12 +936,24 @@ void cloud_drive_authenticate(cloud_drive_t* drive) void cloud_drive_create(void (*ready_callback)(cloud_drive_t*)) { + pending_login = true; + cloud_drive_t* drive = new cloud_drive_t; + std::function fcallback = [ready_callback, drive](cloud_drive_t* called_drive) { + pending_login = false; + ready_callback(called_drive); + + // If this callback is called with a nullptr that means something went wrong + // during authentication and the drive object we created should be deleted + if (called_drive == nullptr) + { + delete drive; + } + }; #ifndef EMSCRIPTEN - std::thread create_thread([ready_callback] { + std::thread create_thread([drive, fcallback] { #endif - cloud_drive_t* drive = new cloud_drive_t; drive->save_directory = se_get_pref_path(); - drive->ready_callback = ready_callback; + drive->ready_callback = fcallback; std::string refresh_path = drive->save_directory + "refresh_token.txt"; if (sb_file_exists(refresh_path.c_str())) @@ -950,22 +963,22 @@ void cloud_drive_create(void (*ready_callback)(cloud_drive_t*)) if (refresh_token_data == NULL) { printf("[cloud] failed to load refresh token\n"); - ready_callback(nullptr); + drive->ready_callback(nullptr); return; } drive->refresh_token = std::string((char*)refresh_token_data, refresh_token_size - 1); free(refresh_token_data); - google_use_refresh_token(drive, [ready_callback, refresh_path](cloud_drive_t* drive) { + google_use_refresh_token(drive, [refresh_path](cloud_drive_t* drive) { if (drive->access_token.empty()) { printf("[cloud] failed to use refresh token\n"); ::remove(refresh_path.c_str()); - ready_callback(nullptr); + drive->ready_callback(nullptr); } else { - google_cloud_drive_init(drive, ready_callback); + google_cloud_drive_init(drive); } }); return; @@ -979,6 +992,7 @@ void cloud_drive_create(void (*ready_callback)(cloud_drive_t*)) void cloud_drive_logout(cloud_drive_t* drive, void (*callback)()) { + pending_logout = true; std::function fcallback = callback; drive->scheduled_deletion = true; // no more requests #ifndef EMSCRIPTEN @@ -993,6 +1007,7 @@ void cloud_drive_logout(cloud_drive_t* drive, void (*callback)()) [drive, fcallback](const std::vector& data) { delete drive; fcallback(); + pending_logout = false; }); em_flush_fs(); @@ -1128,4 +1143,14 @@ void cloud_drive_cleanup() uint64_t cloud_drive_hash(const char* input, size_t input_size) { return XXH64(input, input_size, 0); +} + +bool cloud_drive_pending_login() +{ + return pending_login; +} + +bool cloud_drive_pending_logout() +{ + return pending_logout; } \ No newline at end of file diff --git a/src/cloud.h b/src/cloud.h index 402f831df..58285b8cc 100644 --- a/src/cloud.h +++ b/src/cloud.h @@ -4,6 +4,7 @@ #include #include +#include typedef struct cloud_drive_t cloud_drive_t; @@ -39,5 +40,8 @@ cloud_user_info_t cloud_drive_get_user_info(cloud_drive_t* cloud_drive); void cloud_drive_init(); void cloud_drive_cleanup(); +bool cloud_drive_pending_login(); +bool cloud_drive_pending_logout(); + uint64_t cloud_drive_hash(const char* input, size_t input_size); #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index b830ca0c7..ac52cd65f 100644 --- a/src/main.c +++ b/src/main.c @@ -496,11 +496,6 @@ typedef struct{ }se_emu_id; typedef struct{ cloud_drive_t* drive; - bool awaiting_login; - bool awaiting_login_swap; - bool awaiting_logout; - bool awaiting_logout_swap; - char username[128]; se_save_state_t save_states[SE_NUM_SAVE_STATES]; mutex_t save_states_mutex[SE_NUM_SAVE_STATES]; bool save_states_busy[SE_NUM_SAVE_STATES]; @@ -2819,10 +2814,6 @@ void se_logged_out_cloud_callback(){ cloud_state.drive = NULL; memset(cloud_state.save_states, 0, sizeof(cloud_state.save_states)); memset(cloud_state.save_states_busy_swap, 0, sizeof(cloud_state.save_states_busy_swap)); - cloud_state.awaiting_login = false; - cloud_state.awaiting_logout = false; - cloud_state.awaiting_login_swap = false; - cloud_state.awaiting_logout_swap = false; } void se_write_png_cloud(void* context, void* data, int size){ char file[SB_FILE_PATH_SIZE]; @@ -2851,7 +2842,6 @@ void se_restore_state_slot_cloud(size_t slot){ static void se_drive_ready_callback(cloud_drive_t* drive){ cloud_state.drive = drive; if(drive){ - cloud_state.awaiting_login_swap = false; cloud_state.user_info = cloud_drive_get_user_info(drive); // If there's a game, check if there's any save states to download @@ -2860,11 +2850,9 @@ static void se_drive_ready_callback(cloud_drive_t* drive){ } }else{ printf("Something went wrong during cloud login\n"); - cloud_state.awaiting_login_swap = false; } } void se_login_cloud(){ - cloud_state.awaiting_login_swap = true; cloud_drive_create(se_drive_ready_callback); } static void se_sync_cloud_save_states_callback(){ @@ -2909,7 +2897,7 @@ void se_drive_login(bool clicked, int x, int y, int w, int h){ }; }); } - if(cloud_state.awaiting_login) return; + if(cloud_drive_pending_login()) return; EM_ASM_INT({ var input = document.getElementById('driveLogin'); input.style.left = $0 +'px'; @@ -5741,10 +5729,11 @@ void se_draw_menu_panel(){ } se_section(ICON_FK_CLOUD " Google Drive"); if (!cloud_state.drive){ - if (cloud_state.awaiting_login) se_push_disabled(); + bool pending_login = cloud_drive_pending_login(); + if (pending_login) se_push_disabled(); bool clicked = false; if (se_button(ICON_FK_SIGN_IN " Login",(ImVec2){0,0})){clicked=true;} - if (cloud_state.awaiting_login) se_pop_disabled(); + if (pending_login) se_pop_disabled(); if(igIsItemVisible()){ ImVec2 min, max; igGetItemRectMin(&min); @@ -5754,7 +5743,6 @@ void se_draw_menu_panel(){ max.y+=style->FramePadding.y; se_drive_login(clicked, min.x, min.y, max.x-min.x, max.y-min.y); } - cloud_state.awaiting_login = cloud_state.awaiting_login_swap; } else { ImVec2 avatar_frame_sz = (ImVec2){64+style->FramePadding.x*2,64+style->FramePadding.y*2}; ImVec2 screen_p; @@ -5781,13 +5769,12 @@ void se_draw_menu_panel(){ char logged_in[256]; snprintf(logged_in,256,se_localize_and_cache("Logged in as %s"),cloud_state.user_info.name); se_text(logged_in); - if (cloud_state.awaiting_logout) se_push_disabled(); + bool pending_logout = cloud_drive_pending_logout(); + if (pending_logout) se_push_disabled(); if (se_button(ICON_FK_SIGN_OUT " Logout",(ImVec2){0,0})){ - cloud_state.awaiting_logout_swap = true; cloud_drive_logout(cloud_state.drive,se_logged_out_cloud_callback); } - if (cloud_state.awaiting_logout) se_pop_disabled(); - cloud_state.awaiting_logout = cloud_state.awaiting_logout_swap; + if (pending_logout) se_pop_disabled(); igEndGroup(); } @@ -7098,7 +7085,6 @@ void se_load_settings(){ char refresh_token_path[SB_FILE_PATH_SIZE]; snprintf(refresh_token_path,SB_FILE_PATH_SIZE,"%srefresh_token.txt",se_get_pref_path()); if(sb_file_exists(refresh_token_path)){ - cloud_state.awaiting_login_swap = true; cloud_drive_create(se_drive_ready_callback); } }