Skip to content

Commit a870799

Browse files
rafaelnobrepdzcbenz
authored andcommitted
Exposes more Handoff related APIs to Electron.
1 parent 787675a commit a870799

File tree

9 files changed

+234
-5
lines changed

9 files changed

+234
-5
lines changed

atom/browser/api/atom_api_app.cc

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,17 +584,35 @@ void App::OnAccessibilitySupportChanged() {
584584
}
585585

586586
#if defined(OS_MACOSX)
587+
void App::OnWillContinueUserActivity(
588+
bool* prevent_default,
589+
const std::string& type) {
590+
*prevent_default = Emit("will-continue-activity", type);
591+
}
592+
void App::OnDidFailToContinueUserActivity(
593+
const std::string& type,
594+
const std::string& error) {
595+
Emit("continue-activity-error", type, error);
596+
}
587597
void App::OnContinueUserActivity(
588598
bool* prevent_default,
589599
const std::string& type,
590600
const base::DictionaryValue& user_info) {
591601
*prevent_default = Emit("continue-activity", type, user_info);
592602
}
593-
603+
void App::OnUserActivityWasContinued(
604+
const std::string& type,
605+
const base::DictionaryValue& user_info) {
606+
Emit("activity-was-continued", type, user_info);
607+
}
608+
void App::OnUpdateUserActivityState(
609+
const std::string& type,
610+
const base::DictionaryValue& user_info) {
611+
Emit("update-activity-state", type, user_info);
612+
}
594613
void App::OnNewWindowForTab() {
595614
Emit("new-window-for-tab");
596615
}
597-
598616
#endif
599617

600618
void App::OnLogin(LoginHandler* login_handler,
@@ -1139,6 +1157,10 @@ void App::BuildPrototype(
11391157
base::Bind(&Browser::SetUserActivity, browser))
11401158
.SetMethod("getCurrentActivityType",
11411159
base::Bind(&Browser::GetCurrentActivityType, browser))
1160+
.SetMethod("invalidateCurrentActivity",
1161+
base::Bind(&Browser::InvalidateCurrentActivity, browser))
1162+
.SetMethod("updateCurrentActivity",
1163+
base::Bind(&Browser::UpdateCurrentActivity, browser))
11421164
.SetMethod("setAboutPanelOptions",
11431165
base::Bind(&Browser::SetAboutPanelOptions, browser))
11441166
#endif

atom/browser/api/atom_api_app.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,22 @@ class App : public AtomBrowserClient::Delegate,
113113
const base::DictionaryValue& request_details) override;
114114
void OnAccessibilitySupportChanged() override;
115115
#if defined(OS_MACOSX)
116+
void OnWillContinueUserActivity(
117+
bool* prevent_default,
118+
const std::string& type) override;
119+
void OnDidFailToContinueUserActivity(
120+
const std::string& type,
121+
const std::string& error) override;
116122
void OnContinueUserActivity(
117123
bool* prevent_default,
118124
const std::string& type,
119125
const base::DictionaryValue& user_info) override;
120-
126+
void OnUserActivityWasContinued(
127+
const std::string& type,
128+
const base::DictionaryValue& user_info) override;
129+
void OnUpdateUserActivityState(
130+
const std::string& type,
131+
const base::DictionaryValue& user_info) override;
121132
void OnNewWindowForTab() override;
122133
#endif
123134

atom/browser/browser.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,32 @@ class Browser : public WindowListObserver {
119119
// Returns the type name of the current user activity.
120120
std::string GetCurrentActivityType();
121121

122+
// Invalidates the current user activity.
123+
void InvalidateCurrentActivity();
124+
125+
// Updates the current user activity
126+
void UpdateCurrentActivity(const std::string& type,
127+
const base::DictionaryValue& user_info);
128+
129+
// Indicates that an user activity is about to be resumed.
130+
bool WillContinueUserActivity(const std::string& type);
131+
132+
// Indicates a failure to resume a Handoff activity.
133+
void DidFailToContinueUserActivity(const std::string& type,
134+
const std::string& error);
135+
122136
// Resumes an activity via hand-off.
123137
bool ContinueUserActivity(const std::string& type,
124138
const base::DictionaryValue& user_info);
125139

140+
// Indicates that an activity was continued on another device.
141+
void UserActivityWasContinued(const std::string& type,
142+
const base::DictionaryValue& user_info);
143+
144+
// Gives an oportunity to update the Handoff payload.
145+
void UpdateUserActivityState(const std::string& type,
146+
const base::DictionaryValue& user_info);
147+
126148
// Bounce the dock icon.
127149
enum BounceType {
128150
BOUNCE_CRITICAL = 0,

atom/browser/browser_mac.mm

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,49 @@
144144
return base::SysNSStringToUTF8(userActivity.activityType);
145145
}
146146

147+
void Browser::InvalidateCurrentActivity() {
148+
[[AtomApplication sharedApplication] invalidateCurrentActivity];
149+
}
150+
151+
void Browser::UpdateCurrentActivity(const std::string& type,
152+
const base::DictionaryValue& user_info) {
153+
[[AtomApplication sharedApplication]
154+
updateCurrentActivity:base::SysUTF8ToNSString(type)
155+
withUserInfo:DictionaryValueToNSDictionary(user_info)];
156+
}
157+
158+
bool Browser::WillContinueUserActivity(const std::string& type) {
159+
bool prevent_default = false;
160+
for (BrowserObserver& observer : observers_)
161+
observer.OnWillContinueUserActivity(&prevent_default, type);
162+
return prevent_default;
163+
}
164+
165+
void Browser::DidFailToContinueUserActivity(const std::string& type,
166+
const std::string& error) {
167+
for (BrowserObserver& observer : observers_)
168+
observer.OnDidFailToContinueUserActivity(type, error);
169+
}
170+
147171
bool Browser::ContinueUserActivity(const std::string& type,
148172
const base::DictionaryValue& user_info) {
149173
bool prevent_default = false;
150174
for (BrowserObserver& observer : observers_)
151175
observer.OnContinueUserActivity(&prevent_default, type, user_info);
152176
return prevent_default;
153177
}
178+
179+
void Browser::UserActivityWasContinued(const std::string& type,
180+
const base::DictionaryValue& user_info) {
181+
for (BrowserObserver& observer : observers_)
182+
observer.OnUserActivityWasContinued(type, user_info);
183+
}
184+
185+
void Browser::UpdateUserActivityState(const std::string& type,
186+
const base::DictionaryValue& user_info) {
187+
for (BrowserObserver& observer : observers_)
188+
observer.OnUpdateUserActivityState(type, user_info);
189+
}
154190

155191
Browser::LoginItemSettings Browser::GetLoginItemSettings(
156192
const LoginItemSettings& options) {

atom/browser/browser_observer.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,27 @@ class BrowserObserver {
5656
virtual void OnAccessibilitySupportChanged() {}
5757

5858
#if defined(OS_MACOSX)
59+
// The browser wants to report that an user activity will resume. (macOS only)
60+
virtual void OnWillContinueUserActivity(
61+
bool* prevent_default,
62+
const std::string& type) {}
63+
// The browser wants to report an user activity resuming error. (macOS only)
64+
virtual void OnDidFailToContinueUserActivity(
65+
const std::string& type,
66+
const std::string& error) {}
5967
// The browser wants to resume a user activity via handoff. (macOS only)
6068
virtual void OnContinueUserActivity(
6169
bool* prevent_default,
6270
const std::string& type,
6371
const base::DictionaryValue& user_info) {}
64-
72+
// The browser wants to notify that an user activity was resumed. (macOS only)
73+
virtual void OnUserActivityWasContinued(
74+
const std::string& type,
75+
const base::DictionaryValue& user_info) {}
76+
// The browser wants to update an user activity payload. (macOS only)
77+
virtual void OnUpdateUserActivityState(
78+
const std::string& type,
79+
const base::DictionaryValue& user_info) {}
6580
// User clicked the native macOS new tab button. (macOS only)
6681
virtual void OnNewWindowForTab() {}
6782
#endif

atom/browser/mac/atom_application.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
#import "base/mac/scoped_nsobject.h"
77

88
@interface AtomApplication : NSApplication<CrAppProtocol,
9-
CrAppControlProtocol> {
9+
CrAppControlProtocol,
10+
NSUserActivityDelegate> {
1011
@private
1112
BOOL handlingSendEvent_;
1213
base::scoped_nsobject<NSUserActivity> currentActivity_;
@@ -24,5 +25,8 @@
2425
- (void)setCurrentActivity:(NSString*)type
2526
withUserInfo:(NSDictionary*)userInfo
2627
withWebpageURL:(NSURL*)webpageURL;
28+
- (void)invalidateCurrentActivity;
29+
- (void)updateCurrentActivity:(NSString *)type
30+
withUserInfo:(NSDictionary*)userInfo;
2731

2832
@end

atom/browser/mac/atom_application.mm

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#import "atom/browser/mac/atom_application.h"
66

7+
#include "atom/browser/mac/dict_util.h"
78
#include "atom/browser/browser.h"
89
#include "base/auto_reset.h"
910
#include "base/strings/sys_string_conversions.h"
@@ -35,13 +36,50 @@ - (void)setCurrentActivity:(NSString*)type
3536
[[NSUserActivity alloc] initWithActivityType:type]);
3637
[currentActivity_ setUserInfo:userInfo];
3738
[currentActivity_ setWebpageURL:webpageURL];
39+
[currentActivity_ setDelegate: self];
3840
[currentActivity_ becomeCurrent];
3941
}
4042

4143
- (NSUserActivity*)getCurrentActivity {
4244
return currentActivity_.get();
4345
}
4446

47+
- (void)invalidateCurrentActivity {
48+
if (currentActivity_.get() != NULL) {
49+
[currentActivity_.get() invalidate];
50+
currentActivity_.reset();
51+
}
52+
}
53+
54+
- (void)updateCurrentActivity:(NSString *)type
55+
withUserInfo:(NSDictionary*)userInfo {
56+
if (currentActivity_.get() != NULL) {
57+
[currentActivity_.get() addUserInfoEntriesFromDictionary:userInfo];
58+
}
59+
}
60+
61+
- (void)updateUserActivityState:(NSUserActivity *)userActivity {
62+
std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType));
63+
std::unique_ptr<base::DictionaryValue> user_info =
64+
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
65+
66+
atom::Browser* browser = atom::Browser::Get();
67+
browser->UpdateUserActivityState(activity_type, *user_info);
68+
69+
[super updateUserActivityState:userActivity];
70+
}
71+
72+
- (void)userActivityWasContinued:(NSUserActivity *)userActivity {
73+
std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType));
74+
std::unique_ptr<base::DictionaryValue> user_info =
75+
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
76+
77+
atom::Browser* browser = atom::Browser::Get();
78+
79+
browser->UserActivityWasContinued(activity_type, *user_info);
80+
[userActivity setNeedsSave:YES];
81+
}
82+
4583
- (void)awakeFromNib {
4684
[[NSAppleEventManager sharedAppleEventManager]
4785
setEventHandler:self

atom/browser/mac/atom_application_delegate.mm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,21 @@ - (BOOL)application:(NSApplication*)sender
118118
return browser->ContinueUserActivity(activity_type, *user_info) ? YES : NO;
119119
}
120120

121+
- (BOOL)application:(NSApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType {
122+
std::string activity_type(base::SysNSStringToUTF8(userActivityType));
123+
124+
atom::Browser* browser = atom::Browser::Get();
125+
return browser->WillContinueUserActivity(activity_type) ? YES : NO;
126+
}
127+
128+
- (void)application:(NSApplication *)application didFailToContinueUserActivityWithType:(NSString *)userActivityType error:(NSError *)error {
129+
std::string activity_type(base::SysNSStringToUTF8(userActivityType));
130+
std::string error_message(base::SysNSStringToUTF8([error localizedDescription]));
131+
132+
atom::Browser* browser = atom::Browser::Get();
133+
browser->DidFailToContinueUserActivity(activity_type, error_message);
134+
}
135+
121136
- (IBAction)newWindowForTab:(id)sender {
122137
atom::Browser::Get()->NewWindowForTab();
123138
}

docs/api/app.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,53 @@ ID as the activity's source app and that supports the activity's type.
149149
Supported activity types are specified in the app's `Info.plist` under the
150150
`NSUserActivityTypes` key.
151151

152+
### Event: 'will-continue-activity' _macOS_
153+
154+
Returns:
155+
156+
* `event` Event
157+
* `type` String - A string identifying the activity. Maps to
158+
[`NSUserActivity.activityType`][activity-type].
159+
160+
Emitted during [Handoff][handoff] before an activity from a different device wants
161+
to be resumed. You should call `event.preventDefault()` if you want to handle
162+
this event.
163+
164+
### Event: 'continue-activity-error' _macOS_
165+
166+
Returns:
167+
168+
* `event` Event
169+
* `type` String - A string identifying the activity. Maps to
170+
[`NSUserActivity.activityType`][activity-type].
171+
* `error` String - A string with the error's localized description.
172+
173+
Emitted during [Handoff][handoff] when an activity from a different device
174+
fails to be resumed.
175+
176+
### Event: 'activity-was-continued' _macOS_
177+
178+
Returns:
179+
180+
* `event` Event
181+
* `type` String - A string identifying the activity. Maps to
182+
[`NSUserActivity.activityType`][activity-type].
183+
* `userInfo` Object - Contains app-specific state stored by the activity.
184+
185+
Emitted during [Handoff][handoff] after an activity from this device was successfully
186+
resumed.
187+
188+
### Event: 'update-activity-state' _macOS_
189+
190+
Returns:
191+
192+
* `event` Event
193+
* `type` String - A string identifying the activity. Maps to
194+
[`NSUserActivity.activityType`][activity-type].
195+
* `userInfo` Object - Contains app-specific state stored by the activity.
196+
197+
Emitted during [Handoff][handoff] when its user info should be updated before resuming.
198+
152199
### Event: 'new-window-for-tab' _macOS_
153200

154201
Returns:
@@ -748,6 +795,25 @@ is eligible for [Handoff][handoff] to another device afterward.
748795

749796
Returns `String` - The type of the currently running activity.
750797

798+
### `app.invalidateCurrentActivity()` _macOS_
799+
800+
* `type` String - Uniquely identifies the activity. Maps to
801+
[`NSUserActivity.activityType`][activity-type].
802+
* `userInfo` Object - App-specific state to store for use by another device.
803+
* `webpageURL` String (optional) - The webpage to load in a browser if no suitable app is
804+
installed on the resuming device. The scheme must be `http` or `https`.
805+
806+
Invalidates de current Handoff user activity.
807+
808+
### `app.updateCurrentActivity(type, userInfo[, webpageURL])` _macOS_
809+
810+
* `type` String - Uniquely identifies the activity. Maps to
811+
[`NSUserActivity.activityType`][activity-type].
812+
* `userInfo` Object - App-specific state to store for use by another device.
813+
814+
Updates the current `NSUserActivity` if its type matches `type`, merging the entries from
815+
`userInfo` into its current userInfo dictionary.
816+
751817
### `app.setAppUserModelId(id)` _Windows_
752818

753819
* `id` String

0 commit comments

Comments
 (0)