Merge pull request #5352 from CharlieHess/hands-on-hand-off

OS X Handoff Feature
This commit is contained in:
Cheng Zhao 2016-05-05 12:06:56 +09:00
commit 3f2a25d07c
15 changed files with 222 additions and 26 deletions

View file

@ -20,6 +20,7 @@
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/native_mate_converters/string_map_converter.h"
#include "atom/common/node_includes.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
@ -249,6 +250,12 @@ void App::OnFinishLaunching() {
Emit("ready");
}
void App::OnContinueUserActivity(bool* prevent_default,
const std::string& type,
const std::map<std::string, std::string>& user_info) {
*prevent_default = Emit("continue-activity", type, user_info);
}
void App::OnLogin(LoginHandler* login_handler) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
@ -460,6 +467,10 @@ void App::BuildPrototype(
#if defined(OS_MACOSX)
.SetMethod("hide", base::Bind(&Browser::Hide, browser))
.SetMethod("show", base::Bind(&Browser::Show, browser))
.SetMethod("setUserActivity",
base::Bind(&Browser::SetUserActivity, browser))
.SetMethod("getCurrentActivityType",
base::Bind(&Browser::GetCurrentActivityType, browser))
#endif
#if defined(OS_WIN)
.SetMethod("setUserTasks",

View file

@ -6,6 +6,7 @@
#define ATOM_BROWSER_API_ATOM_API_APP_H_
#include <string>
#include <map>
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/atom_browser_client.h"
@ -71,6 +72,9 @@ class App : public AtomBrowserClient::Delegate,
void OnWillFinishLaunching() override;
void OnFinishLaunching() override;
void OnLogin(LoginHandler* login_handler) override;
void OnContinueUserActivity(bool* prevent_default,
const std::string& type,
const std::map<std::string, std::string>& user_info) override;
// content::ContentBrowserClient:
void AllowCertificateError(

View file

@ -137,6 +137,19 @@ void Browser::Activate(bool has_visible_windows) {
OnActivate(has_visible_windows));
}
#if defined(OS_MACOSX)
bool Browser::ContinueUserActivity(const std::string& type,
const std::map<std::string,
std::string>& user_info) {
bool prevent_default = false;
FOR_EACH_OBSERVER(BrowserObserver,
observers_,
OnContinueUserActivity(&prevent_default, type, user_info));
return prevent_default;
}
#endif
void Browser::WillFinishLaunching() {
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWillFinishLaunching());
}

View file

@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include <map>
#include "base/macros.h"
#include "base/compiler_specific.h"
@ -92,6 +93,17 @@ class Browser : public WindowListObserver {
// Show the application.
void Show();
// Creates an activity and sets it as the one currently in use.
void SetUserActivity(const std::string& type,
const std::map<std::string, std::string>& user_info);
// Returns the type name of the current user activity.
std::string GetCurrentActivityType();
// Resumes an activity via hand-off.
bool ContinueUserActivity(const std::string& type,
const std::map<std::string, std::string>& user_info);
// Bounce the dock icon.
enum BounceType {
BOUNCE_CRITICAL = 0,

View file

@ -69,7 +69,7 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
return false;
NSString* protocol_ns = [NSString stringWithUTF8String:protocol.c_str()];
CFStringRef bundle =
LSCopyDefaultHandlerForURLScheme(base::mac::NSToCFCast(protocol_ns));
NSString* bundleId = static_cast<NSString*>(
@ -77,7 +77,7 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
if (!bundleId)
return false;
// Ensure the comparison is case-insensitive
// Ensure the comparison is case-insensitive
// as LS does not persist the case of the bundle id.
NSComparisonResult result =
[bundleId caseInsensitiveCompare:identifier];
@ -87,6 +87,30 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
void Browser::SetAppUserModelID(const base::string16& name) {
}
void Browser::SetUserActivity(const std::string& type, const std::map<std::string, std::string>& user_info) {
NSString* type_ns = [NSString stringWithUTF8String:type.c_str()];
NSUserActivity* user_activity = [[NSUserActivity alloc] initWithActivityType:type_ns];
base::scoped_nsobject<NSMutableDictionary> user_info_args([[NSMutableDictionary alloc] init]);
for (auto const &pair : user_info) {
NSString* value_ns = [NSString stringWithUTF8String:pair.second.c_str()];
NSString* key_ns = [NSString stringWithUTF8String:pair.first.c_str()];
[user_info_args.get() setObject:value_ns
forKey:key_ns];
}
user_activity.userInfo = user_info_args.get();
[user_activity becomeCurrent];
[[AtomApplication sharedApplication] setCurrentActivity:user_activity];
}
std::string Browser::GetCurrentActivityType() {
NSUserActivity* user_activity = [[AtomApplication sharedApplication] getCurrentActivity];
return base::SysNSStringToUTF8(user_activity.activityType);
}
std::string Browser::GetExecutableFileVersion() const {
return brightray::GetApplicationVersion();
}

View file

@ -6,6 +6,7 @@
#define ATOM_BROWSER_BROWSER_OBSERVER_H_
#include <string>
#include <map>
namespace atom {
@ -45,6 +46,11 @@ class BrowserObserver {
// The browser requests HTTP login.
virtual void OnLogin(LoginHandler* login_handler) {}
// The browser wants to resume a user activity via handoff. (OS X only)
virtual void OnContinueUserActivity(bool* prevent_default,
const std::string& type,
const std::map<std::string, std::string>& user_info) {}
protected:
virtual ~BrowserObserver() {}
};

View file

@ -3,11 +3,13 @@
// found in the LICENSE file.
#import "base/mac/scoped_sending_event.h"
#import "base/mac/scoped_nsobject.h"
@interface AtomApplication : NSApplication<CrAppProtocol,
CrAppControlProtocol> {
@private
BOOL handlingSendEvent_;
base::scoped_nsobject<NSUserActivity> currentActivity_;
}
+ (AtomApplication*)sharedApplication;
@ -18,4 +20,8 @@
// CrAppControlProtocol:
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent;
- (NSUserActivity*)getCurrentActivity;
- (void)setCurrentActivity:(NSUserActivity*)userActivity;
@end

View file

@ -28,6 +28,14 @@
handlingSendEvent_ = handlingSendEvent;
}
- (void)setCurrentActivity:(NSUserActivity*)userActivity {
currentActivity_ = base::scoped_nsobject<NSUserActivity>(userActivity);
}
- (NSUserActivity*)getCurrentActivity {
return currentActivity_.get();
}
- (void)awakeFromNib {
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self

View file

@ -59,4 +59,23 @@
return flag;
}
- (BOOL)application:(NSApplication *)sender
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType));
std::map<std::string, std::string> user_info;
base::scoped_nsobject<NSArray> keys([userActivity.userInfo allKeys]);
for (NSString* key in keys.get()) {
NSString* value = [userActivity.userInfo objectForKey:key];
std::string key_str(base::SysNSStringToUTF8(key));
std::string value_str(base::SysNSStringToUTF8(value));
user_info[key_str] = value_str;
}
atom::Browser* browser = atom::Browser::Get();
return browser->ContinueUserActivity(activity_type, user_info) ? YES : NO;
}
@end