From 9483f0fc14138d56ec57106fcb1a626b3114b0be Mon Sep 17 00:00:00 2001 From: Rafael Nobre Date: Wed, 9 Aug 2017 12:09:47 -0300 Subject: [PATCH] Adds synchronization logic to allow NSUserActivityDelegate to wait Javascript updating the NSUserActiity UserInfo if requested. --- atom/browser/api/atom_api_app.cc | 3 ++- atom/browser/api/atom_api_app.h | 1 + atom/browser/browser.h | 2 +- atom/browser/browser_mac.mm | 6 ++++-- atom/browser/browser_observer.h | 1 + atom/browser/mac/atom_application.h | 2 ++ atom/browser/mac/atom_application.mm | 23 ++++++++++++++++++++++- 7 files changed, 33 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index e9211aec3dd8..3fe6063bdaa3 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -606,9 +606,10 @@ void App::OnUserActivityWasContinued( Emit("activity-was-continued", type, user_info); } void App::OnUpdateUserActivityState( + bool* prevent_default, const std::string& type, const base::DictionaryValue& user_info) { - Emit("update-activity-state", type, user_info); + *prevent_default = Emit("update-activity-state", type, user_info); } void App::OnNewWindowForTab() { Emit("new-window-for-tab"); diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index f78d8ffc13a1..1134046017cf 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -127,6 +127,7 @@ class App : public AtomBrowserClient::Delegate, const std::string& type, const base::DictionaryValue& user_info) override; void OnUpdateUserActivityState( + bool* prevent_default, const std::string& type, const base::DictionaryValue& user_info) override; void OnNewWindowForTab() override; diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 9d18f91e5929..3549d45a8aa1 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -142,7 +142,7 @@ class Browser : public WindowListObserver { const base::DictionaryValue& user_info); // Gives an oportunity to update the Handoff payload. - void UpdateUserActivityState(const std::string& type, + bool UpdateUserActivityState(const std::string& type, const base::DictionaryValue& user_info); // Bounce the dock icon. diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index 7c189c865006..779d488b3c58 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -182,10 +182,12 @@ void Browser::UserActivityWasContinued(const std::string& type, observer.OnUserActivityWasContinued(type, user_info); } -void Browser::UpdateUserActivityState(const std::string& type, +bool Browser::UpdateUserActivityState(const std::string& type, const base::DictionaryValue& user_info) { + bool prevent_default = false; for (BrowserObserver& observer : observers_) - observer.OnUpdateUserActivityState(type, user_info); + observer.OnUpdateUserActivityState(&prevent_default, type, user_info); + return prevent_default; } Browser::LoginItemSettings Browser::GetLoginItemSettings( diff --git a/atom/browser/browser_observer.h b/atom/browser/browser_observer.h index 2944aac13130..d6b2c9954a1d 100644 --- a/atom/browser/browser_observer.h +++ b/atom/browser/browser_observer.h @@ -75,6 +75,7 @@ class BrowserObserver { const base::DictionaryValue& user_info) {} // The browser wants to update an user activity payload. (macOS only) virtual void OnUpdateUserActivityState( + bool* prevent_default, const std::string& type, const base::DictionaryValue& user_info) {} // User clicked the native macOS new tab button. (macOS only) diff --git a/atom/browser/mac/atom_application.h b/atom/browser/mac/atom_application.h index 7e0d552b2082..5a610bded471 100644 --- a/atom/browser/mac/atom_application.h +++ b/atom/browser/mac/atom_application.h @@ -11,6 +11,8 @@ @private BOOL handlingSendEvent_; base::scoped_nsobject currentActivity_; + NSCondition *handoffLock_; + BOOL updateReceived_; } + (AtomApplication*)sharedApplication; diff --git a/atom/browser/mac/atom_application.mm b/atom/browser/mac/atom_application.mm index d825fe42729b..5ab9781965b6 100644 --- a/atom/browser/mac/atom_application.mm +++ b/atom/browser/mac/atom_application.mm @@ -57,17 +57,36 @@ if (currentActivity_.get() != NULL) { [currentActivity_.get() addUserInfoEntriesFromDictionary:userInfo]; } + + [handoffLock_ lock]; + updateReceived_ = YES; + [handoffLock_ signal]; + [handoffLock_ unlock]; } - (void)userActivityWillSave:(NSUserActivity *)userActivity { + + __block BOOL shouldWait = NO; + dispatch_sync(dispatch_get_main_queue(), ^{ std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType)); std::unique_ptr user_info = atom::NSDictionaryToDictionaryValue(userActivity.userInfo); atom::Browser* browser = atom::Browser::Get(); - browser->UpdateUserActivityState(activity_type, *user_info); + shouldWait = browser->UpdateUserActivityState(activity_type, *user_info) ? YES : NO; }); + + if (shouldWait) { + [handoffLock_ lock]; + updateReceived_ = NO; + while (!updateReceived_) { + BOOL isSignaled = [handoffLock_ waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; + if (!isSignaled) { break; } + } + [handoffLock_ unlock]; + } + [userActivity setNeedsSave:YES]; } @@ -90,6 +109,8 @@ andSelector:@selector(handleURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; + + handoffLock_ = [NSCondition new]; } - (void)handleURLEvent:(NSAppleEventDescriptor*)event