Exposes more Handoff related APIs to Electron.

This commit is contained in:
Rafael Nobre 2017-06-26 16:14:44 -03:00 committed by Cheng Zhao
parent 787675ab08
commit a870799c32
9 changed files with 234 additions and 5 deletions

View file

@ -584,17 +584,35 @@ void App::OnAccessibilitySupportChanged() {
}
#if defined(OS_MACOSX)
void App::OnWillContinueUserActivity(
bool* prevent_default,
const std::string& type) {
*prevent_default = Emit("will-continue-activity", type);
}
void App::OnDidFailToContinueUserActivity(
const std::string& type,
const std::string& error) {
Emit("continue-activity-error", type, error);
}
void App::OnContinueUserActivity(
bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) {
*prevent_default = Emit("continue-activity", type, user_info);
}
void App::OnUserActivityWasContinued(
const std::string& type,
const base::DictionaryValue& user_info) {
Emit("activity-was-continued", type, user_info);
}
void App::OnUpdateUserActivityState(
const std::string& type,
const base::DictionaryValue& user_info) {
Emit("update-activity-state", type, user_info);
}
void App::OnNewWindowForTab() {
Emit("new-window-for-tab");
}
#endif
void App::OnLogin(LoginHandler* login_handler,
@ -1139,6 +1157,10 @@ void App::BuildPrototype(
base::Bind(&Browser::SetUserActivity, browser))
.SetMethod("getCurrentActivityType",
base::Bind(&Browser::GetCurrentActivityType, browser))
.SetMethod("invalidateCurrentActivity",
base::Bind(&Browser::InvalidateCurrentActivity, browser))
.SetMethod("updateCurrentActivity",
base::Bind(&Browser::UpdateCurrentActivity, browser))
.SetMethod("setAboutPanelOptions",
base::Bind(&Browser::SetAboutPanelOptions, browser))
#endif

View file

@ -113,11 +113,22 @@ class App : public AtomBrowserClient::Delegate,
const base::DictionaryValue& request_details) override;
void OnAccessibilitySupportChanged() override;
#if defined(OS_MACOSX)
void OnWillContinueUserActivity(
bool* prevent_default,
const std::string& type) override;
void OnDidFailToContinueUserActivity(
const std::string& type,
const std::string& error) override;
void OnContinueUserActivity(
bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnUserActivityWasContinued(
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnUpdateUserActivityState(
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnNewWindowForTab() override;
#endif

View file

@ -119,10 +119,32 @@ class Browser : public WindowListObserver {
// Returns the type name of the current user activity.
std::string GetCurrentActivityType();
// Invalidates the current user activity.
void InvalidateCurrentActivity();
// Updates the current user activity
void UpdateCurrentActivity(const std::string& type,
const base::DictionaryValue& user_info);
// Indicates that an user activity is about to be resumed.
bool WillContinueUserActivity(const std::string& type);
// Indicates a failure to resume a Handoff activity.
void DidFailToContinueUserActivity(const std::string& type,
const std::string& error);
// Resumes an activity via hand-off.
bool ContinueUserActivity(const std::string& type,
const base::DictionaryValue& user_info);
// Indicates that an activity was continued on another device.
void UserActivityWasContinued(const std::string& type,
const base::DictionaryValue& user_info);
// Gives an oportunity to update the Handoff payload.
void UpdateUserActivityState(const std::string& type,
const base::DictionaryValue& user_info);
// Bounce the dock icon.
enum BounceType {
BOUNCE_CRITICAL = 0,

View file

@ -144,6 +144,30 @@ std::string Browser::GetCurrentActivityType() {
return base::SysNSStringToUTF8(userActivity.activityType);
}
void Browser::InvalidateCurrentActivity() {
[[AtomApplication sharedApplication] invalidateCurrentActivity];
}
void Browser::UpdateCurrentActivity(const std::string& type,
const base::DictionaryValue& user_info) {
[[AtomApplication sharedApplication]
updateCurrentActivity:base::SysUTF8ToNSString(type)
withUserInfo:DictionaryValueToNSDictionary(user_info)];
}
bool Browser::WillContinueUserActivity(const std::string& type) {
bool prevent_default = false;
for (BrowserObserver& observer : observers_)
observer.OnWillContinueUserActivity(&prevent_default, type);
return prevent_default;
}
void Browser::DidFailToContinueUserActivity(const std::string& type,
const std::string& error) {
for (BrowserObserver& observer : observers_)
observer.OnDidFailToContinueUserActivity(type, error);
}
bool Browser::ContinueUserActivity(const std::string& type,
const base::DictionaryValue& user_info) {
bool prevent_default = false;
@ -152,6 +176,18 @@ bool Browser::ContinueUserActivity(const std::string& type,
return prevent_default;
}
void Browser::UserActivityWasContinued(const std::string& type,
const base::DictionaryValue& user_info) {
for (BrowserObserver& observer : observers_)
observer.OnUserActivityWasContinued(type, user_info);
}
void Browser::UpdateUserActivityState(const std::string& type,
const base::DictionaryValue& user_info) {
for (BrowserObserver& observer : observers_)
observer.OnUpdateUserActivityState(type, user_info);
}
Browser::LoginItemSettings Browser::GetLoginItemSettings(
const LoginItemSettings& options) {
LoginItemSettings settings;

View file

@ -56,12 +56,27 @@ class BrowserObserver {
virtual void OnAccessibilitySupportChanged() {}
#if defined(OS_MACOSX)
// The browser wants to report that an user activity will resume. (macOS only)
virtual void OnWillContinueUserActivity(
bool* prevent_default,
const std::string& type) {}
// The browser wants to report an user activity resuming error. (macOS only)
virtual void OnDidFailToContinueUserActivity(
const std::string& type,
const std::string& error) {}
// The browser wants to resume a user activity via handoff. (macOS only)
virtual void OnContinueUserActivity(
bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) {}
// The browser wants to notify that an user activity was resumed. (macOS only)
virtual void OnUserActivityWasContinued(
const std::string& type,
const base::DictionaryValue& user_info) {}
// The browser wants to update an user activity payload. (macOS only)
virtual void OnUpdateUserActivityState(
const std::string& type,
const base::DictionaryValue& user_info) {}
// User clicked the native macOS new tab button. (macOS only)
virtual void OnNewWindowForTab() {}
#endif

View file

@ -6,7 +6,8 @@
#import "base/mac/scoped_nsobject.h"
@interface AtomApplication : NSApplication<CrAppProtocol,
CrAppControlProtocol> {
CrAppControlProtocol,
NSUserActivityDelegate> {
@private
BOOL handlingSendEvent_;
base::scoped_nsobject<NSUserActivity> currentActivity_;
@ -24,5 +25,8 @@
- (void)setCurrentActivity:(NSString*)type
withUserInfo:(NSDictionary*)userInfo
withWebpageURL:(NSURL*)webpageURL;
- (void)invalidateCurrentActivity;
- (void)updateCurrentActivity:(NSString *)type
withUserInfo:(NSDictionary*)userInfo;
@end

View file

@ -4,6 +4,7 @@
#import "atom/browser/mac/atom_application.h"
#include "atom/browser/mac/dict_util.h"
#include "atom/browser/browser.h"
#include "base/auto_reset.h"
#include "base/strings/sys_string_conversions.h"
@ -35,6 +36,7 @@
[[NSUserActivity alloc] initWithActivityType:type]);
[currentActivity_ setUserInfo:userInfo];
[currentActivity_ setWebpageURL:webpageURL];
[currentActivity_ setDelegate: self];
[currentActivity_ becomeCurrent];
}
@ -42,6 +44,42 @@
return currentActivity_.get();
}
- (void)invalidateCurrentActivity {
if (currentActivity_.get() != NULL) {
[currentActivity_.get() invalidate];
currentActivity_.reset();
}
}
- (void)updateCurrentActivity:(NSString *)type
withUserInfo:(NSDictionary*)userInfo {
if (currentActivity_.get() != NULL) {
[currentActivity_.get() addUserInfoEntriesFromDictionary:userInfo];
}
}
- (void)updateUserActivityState:(NSUserActivity *)userActivity {
std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType));
std::unique_ptr<base::DictionaryValue> user_info =
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
atom::Browser* browser = atom::Browser::Get();
browser->UpdateUserActivityState(activity_type, *user_info);
[super updateUserActivityState:userActivity];
}
- (void)userActivityWasContinued:(NSUserActivity *)userActivity {
std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType));
std::unique_ptr<base::DictionaryValue> user_info =
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
atom::Browser* browser = atom::Browser::Get();
browser->UserActivityWasContinued(activity_type, *user_info);
[userActivity setNeedsSave:YES];
}
- (void)awakeFromNib {
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self

View file

@ -118,6 +118,21 @@ continueUserActivity:(NSUserActivity*)userActivity
return browser->ContinueUserActivity(activity_type, *user_info) ? YES : NO;
}
- (BOOL)application:(NSApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType {
std::string activity_type(base::SysNSStringToUTF8(userActivityType));
atom::Browser* browser = atom::Browser::Get();
return browser->WillContinueUserActivity(activity_type) ? YES : NO;
}
- (void)application:(NSApplication *)application didFailToContinueUserActivityWithType:(NSString *)userActivityType error:(NSError *)error {
std::string activity_type(base::SysNSStringToUTF8(userActivityType));
std::string error_message(base::SysNSStringToUTF8([error localizedDescription]));
atom::Browser* browser = atom::Browser::Get();
browser->DidFailToContinueUserActivity(activity_type, error_message);
}
- (IBAction)newWindowForTab:(id)sender {
atom::Browser::Get()->NewWindowForTab();
}

View file

@ -149,6 +149,53 @@ ID as the activity's source app and that supports the activity's type.
Supported activity types are specified in the app's `Info.plist` under the
`NSUserActivityTypes` key.
### Event: 'will-continue-activity' _macOS_
Returns:
* `event` Event
* `type` String - A string identifying the activity. Maps to
[`NSUserActivity.activityType`][activity-type].
Emitted during [Handoff][handoff] before an activity from a different device wants
to be resumed. You should call `event.preventDefault()` if you want to handle
this event.
### Event: 'continue-activity-error' _macOS_
Returns:
* `event` Event
* `type` String - A string identifying the activity. Maps to
[`NSUserActivity.activityType`][activity-type].
* `error` String - A string with the error's localized description.
Emitted during [Handoff][handoff] when an activity from a different device
fails to be resumed.
### Event: 'activity-was-continued' _macOS_
Returns:
* `event` Event
* `type` String - A string identifying the activity. Maps to
[`NSUserActivity.activityType`][activity-type].
* `userInfo` Object - Contains app-specific state stored by the activity.
Emitted during [Handoff][handoff] after an activity from this device was successfully
resumed.
### Event: 'update-activity-state' _macOS_
Returns:
* `event` Event
* `type` String - A string identifying the activity. Maps to
[`NSUserActivity.activityType`][activity-type].
* `userInfo` Object - Contains app-specific state stored by the activity.
Emitted during [Handoff][handoff] when its user info should be updated before resuming.
### Event: 'new-window-for-tab' _macOS_
Returns:
@ -748,6 +795,25 @@ is eligible for [Handoff][handoff] to another device afterward.
Returns `String` - The type of the currently running activity.
### `app.invalidateCurrentActivity()` _macOS_
* `type` String - Uniquely identifies the activity. Maps to
[`NSUserActivity.activityType`][activity-type].
* `userInfo` Object - App-specific state to store for use by another device.
* `webpageURL` String (optional) - The webpage to load in a browser if no suitable app is
installed on the resuming device. The scheme must be `http` or `https`.
Invalidates de current Handoff user activity.
### `app.updateCurrentActivity(type, userInfo[, webpageURL])` _macOS_
* `type` String - Uniquely identifies the activity. Maps to
[`NSUserActivity.activityType`][activity-type].
* `userInfo` Object - App-specific state to store for use by another device.
Updates the current `NSUserActivity` if its type matches `type`, merging the entries from
`userInfo` into its current userInfo dictionary.
### `app.setAppUserModelId(id)` _Windows_
* `id` String