electron_api_shell.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include <string>
  5. #include "shell/common/gin_converters/callback_converter.h"
  6. #include "shell/common/gin_converters/file_path_converter.h"
  7. #include "shell/common/gin_converters/guid_converter.h"
  8. #include "shell/common/gin_converters/gurl_converter.h"
  9. #include "shell/common/gin_helper/dictionary.h"
  10. #include "shell/common/gin_helper/error_thrower.h"
  11. #include "shell/common/gin_helper/promise.h"
  12. #include "shell/common/node_includes.h"
  13. #include "shell/common/platform_util.h"
  14. #if BUILDFLAG(IS_WIN)
  15. #include "base/win/scoped_com_initializer.h"
  16. #include "base/win/shortcut.h"
  17. namespace gin {
  18. template <>
  19. struct Converter<base::win::ShortcutOperation> {
  20. static bool FromV8(v8::Isolate* isolate,
  21. v8::Handle<v8::Value> val,
  22. base::win::ShortcutOperation* out) {
  23. std::string operation;
  24. if (!ConvertFromV8(isolate, val, &operation))
  25. return false;
  26. if (operation.empty() || operation == "create")
  27. *out = base::win::ShortcutOperation::kCreateAlways;
  28. else if (operation == "update")
  29. *out = base::win::ShortcutOperation::kUpdateExisting;
  30. else if (operation == "replace")
  31. *out = base::win::ShortcutOperation::kReplaceExisting;
  32. else
  33. return false;
  34. return true;
  35. }
  36. };
  37. } // namespace gin
  38. #endif
  39. namespace {
  40. void OnOpenFinished(gin_helper::Promise<void> promise,
  41. const std::string& error) {
  42. if (error.empty())
  43. promise.Resolve();
  44. else
  45. promise.RejectWithErrorMessage(error.c_str());
  46. }
  47. v8::Local<v8::Promise> OpenExternal(const GURL& url, gin::Arguments* args) {
  48. gin_helper::Promise<void> promise(args->isolate());
  49. v8::Local<v8::Promise> handle = promise.GetHandle();
  50. platform_util::OpenExternalOptions options;
  51. if (args->Length() >= 2) {
  52. gin::Dictionary obj(nullptr);
  53. if (args->GetNext(&obj)) {
  54. obj.Get("activate", &options.activate);
  55. obj.Get("workingDirectory", &options.working_dir);
  56. }
  57. }
  58. platform_util::OpenExternal(
  59. url, options, base::BindOnce(&OnOpenFinished, std::move(promise)));
  60. return handle;
  61. }
  62. v8::Local<v8::Promise> OpenPath(v8::Isolate* isolate,
  63. const base::FilePath& full_path) {
  64. gin_helper::Promise<const std::string&> promise(isolate);
  65. v8::Local<v8::Promise> handle = promise.GetHandle();
  66. platform_util::OpenPath(
  67. full_path,
  68. base::BindOnce(
  69. [](gin_helper::Promise<const std::string&> promise,
  70. const std::string& err_msg) { promise.Resolve(err_msg); },
  71. std::move(promise)));
  72. return handle;
  73. }
  74. v8::Local<v8::Promise> TrashItem(v8::Isolate* isolate,
  75. const base::FilePath& path) {
  76. gin_helper::Promise<void> promise(isolate);
  77. v8::Local<v8::Promise> handle = promise.GetHandle();
  78. platform_util::TrashItem(
  79. path, base::BindOnce(
  80. [](gin_helper::Promise<void> promise, bool success,
  81. const std::string& error) {
  82. if (success) {
  83. promise.Resolve();
  84. } else {
  85. promise.RejectWithErrorMessage(error);
  86. }
  87. },
  88. std::move(promise)));
  89. return handle;
  90. }
  91. #if BUILDFLAG(IS_WIN)
  92. bool WriteShortcutLink(const base::FilePath& shortcut_path,
  93. gin_helper::Arguments* args) {
  94. base::win::ShortcutOperation operation =
  95. base::win::ShortcutOperation::kCreateAlways;
  96. args->GetNext(&operation);
  97. gin::Dictionary options = gin::Dictionary::CreateEmpty(args->isolate());
  98. if (!args->GetNext(&options)) {
  99. args->ThrowError();
  100. return false;
  101. }
  102. base::win::ShortcutProperties properties;
  103. base::FilePath path;
  104. std::wstring str;
  105. UUID toastActivatorClsid;
  106. int index;
  107. if (options.Get("target", &path))
  108. properties.set_target(path);
  109. if (options.Get("cwd", &path))
  110. properties.set_working_dir(path);
  111. if (options.Get("args", &str))
  112. properties.set_arguments(str);
  113. if (options.Get("description", &str))
  114. properties.set_description(str);
  115. if (options.Get("icon", &path) && options.Get("iconIndex", &index))
  116. properties.set_icon(path, index);
  117. if (options.Get("appUserModelId", &str))
  118. properties.set_app_id(str);
  119. if (options.Get("toastActivatorClsid", &toastActivatorClsid))
  120. properties.set_toast_activator_clsid(toastActivatorClsid);
  121. base::win::ScopedCOMInitializer com_initializer;
  122. return base::win::CreateOrUpdateShortcutLink(shortcut_path, properties,
  123. operation);
  124. }
  125. v8::Local<v8::Value> ReadShortcutLink(gin_helper::ErrorThrower thrower,
  126. const base::FilePath& path) {
  127. using base::win::ShortcutProperties;
  128. gin::Dictionary options = gin::Dictionary::CreateEmpty(thrower.isolate());
  129. base::win::ScopedCOMInitializer com_initializer;
  130. base::win::ShortcutProperties properties;
  131. if (!base::win::ResolveShortcutProperties(
  132. path, ShortcutProperties::PROPERTIES_ALL, &properties)) {
  133. thrower.ThrowError("Failed to read shortcut link");
  134. return v8::Null(thrower.isolate());
  135. }
  136. options.Set("target", properties.target);
  137. options.Set("cwd", properties.working_dir);
  138. options.Set("args", properties.arguments);
  139. options.Set("description", properties.description);
  140. options.Set("icon", properties.icon);
  141. options.Set("iconIndex", properties.icon_index);
  142. options.Set("appUserModelId", properties.app_id);
  143. options.Set("toastActivatorClsid", properties.toast_activator_clsid);
  144. return gin::ConvertToV8(thrower.isolate(), options);
  145. }
  146. #endif
  147. void Initialize(v8::Local<v8::Object> exports,
  148. v8::Local<v8::Value> unused,
  149. v8::Local<v8::Context> context,
  150. void* priv) {
  151. gin_helper::Dictionary dict(context->GetIsolate(), exports);
  152. dict.SetMethod("showItemInFolder", &platform_util::ShowItemInFolder);
  153. dict.SetMethod("openPath", &OpenPath);
  154. dict.SetMethod("openExternal", &OpenExternal);
  155. dict.SetMethod("trashItem", &TrashItem);
  156. dict.SetMethod("beep", &platform_util::Beep);
  157. #if BUILDFLAG(IS_WIN)
  158. dict.SetMethod("writeShortcutLink", &WriteShortcutLink);
  159. dict.SetMethod("readShortcutLink", &ReadShortcutLink);
  160. #endif
  161. }
  162. } // namespace
  163. NODE_LINKED_MODULE_CONTEXT_AWARE(electron_common_shell, Initialize)