diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index f15fad9d47f..52a6926d1a9 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -20,7 +20,6 @@ #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" @@ -250,11 +249,14 @@ void App::OnFinishLaunching() { Emit("ready"); } -void App::OnContinueUserActivity(bool* prevent_default, - const std::string& type, - const std::map& user_info) { +#if defined(OS_MACOSX) +void App::OnContinueUserActivity( + bool* prevent_default, + const std::string& type, + const base::DictionaryValue& user_info) { *prevent_default = Emit("continue-activity", type, user_info); } +#endif void App::OnLogin(LoginHandler* login_handler) { v8::Locker locker(isolate()); diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 321230d711e..edfd09c4d28 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -6,7 +6,6 @@ #define ATOM_BROWSER_API_ATOM_API_APP_H_ #include -#include #include "atom/browser/api/event_emitter.h" #include "atom/browser/atom_browser_client.h" @@ -72,9 +71,12 @@ 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& user_info) override; +#if defined(OS_MACOSX) + void OnContinueUserActivity( + bool* prevent_default, + const std::string& type, + const base::DictionaryValue& user_info) override; +#endif // content::ContentBrowserClient: void AllowCertificateError( diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index ee2a225246b..093209ef7c4 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -137,19 +137,6 @@ 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& 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()); } diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 5c3dcaf5122..eb8d2865ad8 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -7,7 +7,6 @@ #include #include -#include #include "base/macros.h" #include "base/compiler_specific.h" @@ -95,14 +94,14 @@ class Browser : public WindowListObserver { // Creates an activity and sets it as the one currently in use. void SetUserActivity(const std::string& type, - const std::map& user_info); + const base::DictionaryValue& 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& user_info); + const base::DictionaryValue& user_info); // Bounce the dock icon. enum BounceType { diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index 42d10debd09..eb7191b67a2 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -6,6 +6,7 @@ #include "atom/browser/mac/atom_application.h" #include "atom/browser/mac/atom_application_delegate.h" +#include "atom/browser/mac/dict_util.h" #include "atom/browser/native_window.h" #include "atom/browser/window_list.h" #include "base/mac/bundle_locations.h" @@ -87,28 +88,28 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) { void Browser::SetAppUserModelID(const base::string16& name) { } -void Browser::SetUserActivity(const std::string& type, const std::map& user_info) { - NSString* type_ns = [NSString stringWithUTF8String:type.c_str()]; - NSUserActivity* user_activity = [[NSUserActivity alloc] initWithActivityType:type_ns]; - - base::scoped_nsobject 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]; +void Browser::SetUserActivity( + const std::string& type, + const base::DictionaryValue& user_info) { + [[AtomApplication sharedApplication] + setCurrentActivity:base::SysUTF8ToNSString(type) + withUserInfo:DictionaryValueToNSDictionary(user_info)]; } std::string Browser::GetCurrentActivityType() { - NSUserActivity* user_activity = [[AtomApplication sharedApplication] getCurrentActivity]; - return base::SysNSStringToUTF8(user_activity.activityType); + NSUserActivity* userActivity = + [[AtomApplication sharedApplication] getCurrentActivity]; + return base::SysNSStringToUTF8(userActivity.activityType); +} + +bool Browser::ContinueUserActivity( + const std::string& type, + const base::DictionaryValue& user_info) { + bool prevent_default = false; + FOR_EACH_OBSERVER(BrowserObserver, + observers_, + OnContinueUserActivity(&prevent_default, type, user_info)); + return prevent_default; } std::string Browser::GetExecutableFileVersion() const { diff --git a/atom/browser/browser_observer.h b/atom/browser/browser_observer.h index 4ad001370c0..c8b0082beb7 100644 --- a/atom/browser/browser_observer.h +++ b/atom/browser/browser_observer.h @@ -6,7 +6,12 @@ #define ATOM_BROWSER_BROWSER_OBSERVER_H_ #include -#include + +#include "build/build_config.h" + +namespace base { +class DictionaryValue; +} namespace atom { @@ -46,10 +51,13 @@ class BrowserObserver { // The browser requests HTTP login. virtual void OnLogin(LoginHandler* login_handler) {} +#if defined(OS_MACOSX) // 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& user_info) {} + virtual void OnContinueUserActivity( + bool* prevent_default, + const std::string& type, + const base::DictionaryValue& user_info) {} +#endif protected: virtual ~BrowserObserver() {} diff --git a/atom/browser/mac/atom_application.h b/atom/browser/mac/atom_application.h index 37074cae7bf..e6489b75fb9 100644 --- a/atom/browser/mac/atom_application.h +++ b/atom/browser/mac/atom_application.h @@ -21,7 +21,6 @@ - (void)setHandlingSendEvent:(BOOL)handlingSendEvent; - (NSUserActivity*)getCurrentActivity; - -- (void)setCurrentActivity:(NSUserActivity*)userActivity; +- (void)setCurrentActivity:(NSString*)type withUserInfo:(NSDictionary*)userInfo; @end diff --git a/atom/browser/mac/atom_application.mm b/atom/browser/mac/atom_application.mm index 18115113047..fa91836f29e 100644 --- a/atom/browser/mac/atom_application.mm +++ b/atom/browser/mac/atom_application.mm @@ -28,8 +28,12 @@ handlingSendEvent_ = handlingSendEvent; } -- (void)setCurrentActivity:(NSUserActivity*)userActivity { - currentActivity_ = base::scoped_nsobject(userActivity); +- (void)setCurrentActivity:(NSString*)type + withUserInfo:(NSDictionary*)userInfo { + currentActivity_ = base::scoped_nsobject( + [[NSUserActivity alloc] initWithActivityType:type]); + [currentActivity_ setUserInfo:userInfo]; + [currentActivity_ becomeCurrent]; } - (NSUserActivity*)getCurrentActivity { diff --git a/atom/browser/mac/atom_application_delegate.mm b/atom/browser/mac/atom_application_delegate.mm index 0904679c49a..7fa3b3027f6 100644 --- a/atom/browser/mac/atom_application_delegate.mm +++ b/atom/browser/mac/atom_application_delegate.mm @@ -6,7 +6,9 @@ #import "atom/browser/mac/atom_application.h" #include "atom/browser/browser.h" +#include "atom/browser/mac/dict_util.h" #include "base/strings/sys_string_conversions.h" +#include "base/values.h" @implementation AtomApplicationDelegate @@ -59,23 +61,17 @@ return flag; } -- (BOOL)application:(NSApplication *)sender -continueUserActivity:(NSUserActivity *)userActivity - restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { +- (BOOL)application:(NSApplication*)sender +continueUserActivity:(NSUserActivity*)userActivity + restorationHandler:(void (^)(NSArray*restorableObjects))restorationHandler { std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType)); - - std::map user_info; - base::scoped_nsobject 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; - } + scoped_ptr user_info = + atom::NSDictionaryToDictionaryValue(userActivity.userInfo); + if (!user_info) + return NO; atom::Browser* browser = atom::Browser::Get(); - return browser->ContinueUserActivity(activity_type, user_info) ? YES : NO; + return browser->ContinueUserActivity(activity_type, *user_info) ? YES : NO; } @end diff --git a/atom/browser/mac/dict_util.h b/atom/browser/mac/dict_util.h new file mode 100644 index 00000000000..e5b293652d8 --- /dev/null +++ b/atom/browser/mac/dict_util.h @@ -0,0 +1,26 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_MAC_DICT_UTIL_H_ +#define ATOM_BROWSER_MAC_DICT_UTIL_H_ + +#import + +#include "base/memory/scoped_ptr.h" + +namespace base { +class Value; +class DictionaryValue; +} + +namespace atom { + +NSDictionary* DictionaryValueToNSDictionary(const base::DictionaryValue& value); + +scoped_ptr NSDictionaryToDictionaryValue( + NSDictionary* dict); + +} // namespace atom + +#endif // ATOM_BROWSER_MAC_DICT_UTIL_H_ diff --git a/atom/browser/mac/dict_util.mm b/atom/browser/mac/dict_util.mm new file mode 100644 index 00000000000..6a98e4cfdaa --- /dev/null +++ b/atom/browser/mac/dict_util.mm @@ -0,0 +1,42 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/mac/dict_util.h" + +#include "base/mac/scoped_nsobject.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/values.h" + +namespace atom { + +NSDictionary* DictionaryValueToNSDictionary(const base::DictionaryValue& value) { + std::string json; + if (!base::JSONWriter::Write(value, &json)) + return nil; + NSData* jsonData = [NSData dataWithBytes:json.c_str() length:json.length()]; + id obj = [NSJSONSerialization JSONObjectWithData:jsonData + options:0 + error:nil]; + if (![obj isKindOfClass:[NSDictionary class]]) + return nil; + return obj; +} + +scoped_ptr NSDictionaryToDictionaryValue( + NSDictionary* dict) { + NSData* data = [NSJSONSerialization dataWithJSONObject:dict + options:0 + error:nil]; + if (!data) + return nullptr; + + base::scoped_nsobject json = + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + scoped_ptr value = + base::JSONReader::Read([json UTF8String]); + return base::DictionaryValue::From(std::move(value)); +} + +} // namespace atom diff --git a/atom/common/api/atom_api_crash_reporter.cc b/atom/common/api/atom_api_crash_reporter.cc index 5db1461f88c..e1932ad7f5f 100644 --- a/atom/common/api/atom_api_crash_reporter.cc +++ b/atom/common/api/atom_api_crash_reporter.cc @@ -6,7 +6,6 @@ #include #include "atom/common/crash_reporter/crash_reporter.h" -#include "atom/common/native_mate_converters/string_map_converter.h" #include "base/bind.h" #include "native_mate/dictionary.h" @@ -16,6 +15,24 @@ using crash_reporter::CrashReporter; namespace mate { +template<> +struct Converter > { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + std::map* out) { + if (!val->IsObject()) + return false; + + v8::Local dict = val->ToObject(); + v8::Local keys = dict->GetOwnPropertyNames(); + for (uint32_t i = 0; i < keys->Length(); ++i) { + v8::Local key = keys->Get(i); + (*out)[V8ToString(key)] = V8ToString(dict->Get(key)); + } + return true; + } +}; + template<> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, diff --git a/atom/common/native_mate_converters/string_map_converter.cc b/atom/common/native_mate_converters/string_map_converter.cc deleted file mode 100644 index 475b052ba65..00000000000 --- a/atom/common/native_mate_converters/string_map_converter.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/common/native_mate_converters/string_map_converter.h" - -namespace mate { - -bool Converter>::FromV8(v8::Isolate* isolate, - v8::Local val, - std::map* out) { - if (!val->IsObject()) - return false; - - v8::Local dict = val->ToObject(); - v8::Local keys = dict->GetOwnPropertyNames(); - for (uint32_t i = 0; i < keys->Length(); ++i) { - v8::Local key = keys->Get(i); - (*out)[V8ToString(key)] = V8ToString(dict->Get(key)); - } - return true; -} - -v8::Local Converter>::ToV8( - v8::Isolate* isolate, - const std::map& in) { - mate::Dictionary dict(isolate, v8::Object::New(isolate)); - - for (auto const &pair : in) { - dict.Set(pair.first, pair.second); - } - - return dict.GetHandle(); -} - -} // namespace mate diff --git a/atom/common/native_mate_converters/string_map_converter.h b/atom/common/native_mate_converters/string_map_converter.h deleted file mode 100644 index 54e4297714c..00000000000 --- a/atom/common/native_mate_converters/string_map_converter.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_STRING_MAP_CONVERTER_H_ -#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_STRING_MAP_CONVERTER_H_ - -#include -#include - -#include "native_mate/converter.h" -#include "native_mate/dictionary.h" - -namespace mate { - -template<> -struct Converter> { - static bool FromV8(v8::Isolate* isolate, - v8::Local val, - std::map* out); - - static v8::Local ToV8(v8::Isolate* isolate, - const std::map& in); -}; - -} // namespace mate - -#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_STRING_MAP_CONVERTER_H_ diff --git a/docs/api/app.md b/docs/api/app.md index 3ade1da034f..fc31d465f7a 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -116,17 +116,18 @@ the application's dock icon. Returns: * `event` Event -* `type` String - A string identifying the event. Maps to [`NSUserActivity.activityType`](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType). +* `type` String - A string identifying the activity. Maps to + [`NSUserActivity.activityType`][activity-type]. * `userInfo` Object - Contains app-specific state stored by the activity on -another device. Currently only string data is supported. + another device. -Emitted during [handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) when an activity from a different device wants to be -resumed. You should call `event.preventDefault()` if you want to handle this -event. +Emitted during [Handoff][handoff] when an activity from a different device wants +to be resumed. You should call `event.preventDefault()` if you want to handle +this event. -A user activity can be continued only in an app that has the same developer -Team 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 +A user activity can be continued only in an app that has the same developer Team +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: 'browser-window-blur' @@ -502,13 +503,12 @@ app.on('ready', function() { ### `app.setUserActivity(type, userInfo)` _OS X_ -* `type` String - Uniquely identifies the activity. It's recommended to use a -reverse-DNS string. +* `type` String - Uniquely identifies the activity. Maps to + [`NSUserActivity.activityType`][activity-type]. * `userInfo` Object - App-specific state to store for use by another device. -Currently only string data is supported. Creates an `NSUserActivity` and sets it as the current activity. The activity -is eligible for [handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) to another device afterward. +is eligible for [Handoff][handoff] to another device afterward. ### `app.getCurrentActivityType()` _OS X_ @@ -600,5 +600,6 @@ Sets the `image` associated with this dock icon. [tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx [CFBundleURLTypes]: https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115 -[LSCopyDefaultHandlerForURLScheme]: -https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme +[LSCopyDefaultHandlerForURLScheme]: https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme +[handoff]: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html +[activity-type]: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType diff --git a/filenames.gypi b/filenames.gypi index f0e3942a5e2..8e0c858dfc8 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -183,6 +183,8 @@ 'atom/browser/mac/atom_application.mm', 'atom/browser/mac/atom_application_delegate.h', 'atom/browser/mac/atom_application_delegate.mm', + 'atom/browser/mac/dict_util.h', + 'atom/browser/mac/dict_util.mm', 'atom/browser/native_window.cc', 'atom/browser/native_window.h', 'atom/browser/native_window_views_win.cc', @@ -361,8 +363,6 @@ 'atom/common/native_mate_converters/image_converter.h', 'atom/common/native_mate_converters/net_converter.cc', 'atom/common/native_mate_converters/net_converter.h', - 'atom/common/native_mate_converters/string_map_converter.cc', - 'atom/common/native_mate_converters/string_map_converter.h', 'atom/common/native_mate_converters/string16_converter.h', 'atom/common/native_mate_converters/ui_base_types_converter.h', 'atom/common/native_mate_converters/v8_value_converter.cc', diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index 30df5361041..8afa90bb9f9 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -91,7 +91,7 @@ describe('app module', function () { }) describe('app.setUserActivity(type, userInfo)', function () { - if (isCI && process.platform !== 'darwin') { + if (process.platform !== 'darwin') { return }