Browse Source

chore: remove native_mate (Part 2) (#20106)

* add notice to files being removed

* add gin version of function_template.h

* rename callback.h to avoid confliction

* add gin version of callback_converter

* add gin converter for OnceCallback

* remove callback_converter_gin_adapter.h

* remove gin_util.h and gin_utils.h

* fix lint warning

* add helper for setting methods
Cheng Zhao 5 years ago
parent
commit
81ae154714
42 changed files with 866 additions and 202 deletions
  1. 8 5
      filenames.gni
  2. 4 0
      native_mate/native_mate/arguments.h
  3. 4 0
      native_mate/native_mate/function_template.h
  4. 1 1
      shell/browser/api/atom_api_app.cc
  5. 1 1
      shell/browser/api/atom_api_app.h
  6. 1 1
      shell/browser/api/atom_api_auto_updater.cc
  7. 1 1
      shell/browser/api/atom_api_browser_window.cc
  8. 1 1
      shell/browser/api/atom_api_content_tracing.cc
  9. 1 1
      shell/browser/api/atom_api_cookies.cc
  10. 1 1
      shell/browser/api/atom_api_debugger.cc
  11. 12 28
      shell/browser/api/atom_api_dialog.cc
  12. 1 1
      shell/browser/api/atom_api_download_item.cc
  13. 1 1
      shell/browser/api/atom_api_global_shortcut.cc
  14. 1 1
      shell/browser/api/atom_api_in_app_purchase.cc
  15. 1 1
      shell/browser/api/atom_api_menu.cc
  16. 1 1
      shell/browser/api/atom_api_net_log.cc
  17. 1 1
      shell/browser/api/atom_api_power_monitor.cc
  18. 1 1
      shell/browser/api/atom_api_session.cc
  19. 1 1
      shell/browser/api/atom_api_system_preferences.cc
  20. 1 1
      shell/browser/api/atom_api_top_level_window.cc
  21. 1 1
      shell/browser/api/atom_api_web_request_ns.cc
  22. 1 1
      shell/browser/atom_download_manager_delegate.cc
  23. 1 1
      shell/browser/net/node_stream_loader.cc
  24. 1 1
      shell/common/api/atom_api_asar.cc
  25. 20 17
      shell/common/api/atom_api_crash_reporter.cc
  26. 1 1
      shell/common/api/atom_api_shell.cc
  27. 0 27
      shell/common/api/gin_utils.h
  28. 1 1
      shell/common/deprecate_util.cc
  29. 59 0
      shell/common/gin_converters/callback_converter.h
  30. 0 44
      shell/common/gin_converters/callback_converter_gin_adapter.h
  31. 17 23
      shell/common/gin_helper/callback.cc
  32. 163 0
      shell/common/gin_helper/callback.h
  33. 84 0
      shell/common/gin_helper/dictionary.h
  34. 36 0
      shell/common/gin_helper/function_template.cc
  35. 263 0
      shell/common/gin_helper/function_template.h
  36. 0 29
      shell/common/gin_util.h
  37. 163 0
      shell/common/native_mate_converters/callback_converter_deprecated.cc
  38. 7 3
      shell/common/native_mate_converters/callback_converter_deprecated.h
  39. 1 1
      shell/common/native_mate_converters/content_converter.cc
  40. 1 1
      shell/common/native_mate_converters/once_callback.h
  41. 1 1
      shell/common/promise_util.h
  42. 1 1
      shell/renderer/api/atom_api_web_frame.cc

+ 8 - 5
filenames.gni

@@ -437,7 +437,6 @@ filenames = {
     "shell/common/api/event_emitter_caller.cc",
     "shell/common/api/event_emitter_caller.h",
     "shell/common/api/features.cc",
-    "shell/common/api/gin_utils.h",
     "shell/common/api/locker.cc",
     "shell/common/api/locker.h",
     "shell/common/api/object_life_monitor.cc",
@@ -475,7 +474,7 @@ filenames = {
     "shell/common/crash_reporter/linux/crash_dump_handler.h",
     "shell/common/crash_reporter/win/crash_service_main.cc",
     "shell/common/crash_reporter/win/crash_service_main.h",
-    "shell/common/gin_converters/callback_converter_gin_adapter.h",
+    "shell/common/gin_converters/callback_converter.h",
     "shell/common/gin_converters/file_dialog_converter.cc",
     "shell/common/gin_converters/file_dialog_converter.h",
     "shell/common/gin_converters/file_path_converter.h",
@@ -489,9 +488,13 @@ filenames = {
     "shell/common/gin_converters/net_converter.h",
     "shell/common/gin_converters/std_converter.h",
     "shell/common/gin_converters/value_converter_gin_adapter.h",
+    "shell/common/gin_helper/callback.cc",
+    "shell/common/gin_helper/callback.h",
     "shell/common/gin_helper/destroyable.cc",
     "shell/common/gin_helper/destroyable.h",
-    "shell/common/gin_util.h",
+    "shell/common/gin_helper/dictionary.h",
+    "shell/common/gin_helper/function_template.cc",
+    "shell/common/gin_helper/function_template.h",
     "shell/common/heap_snapshot.cc",
     "shell/common/heap_snapshot.h",
     "shell/common/key_weak_map.h",
@@ -509,8 +512,8 @@ filenames = {
     "shell/common/native_mate_converters/accelerator_converter.h",
     "shell/common/native_mate_converters/blink_converter.cc",
     "shell/common/native_mate_converters/blink_converter.h",
-    "shell/common/native_mate_converters/callback.cc",
-    "shell/common/native_mate_converters/callback.h",
+    "shell/common/native_mate_converters/callback_converter_deprecated.cc",
+    "shell/common/native_mate_converters/callback_converter_deprecated.h",
     "shell/common/native_mate_converters/content_converter.cc",
     "shell/common/native_mate_converters/content_converter.h",
     "shell/common/native_mate_converters/file_dialog_converter.h",

+ 4 - 0
native_mate/native_mate/arguments.h

@@ -12,6 +12,10 @@
 #include "base/optional.h"
 #include "native_mate/converter.h"
 
+// =============================== NOTICE ===============================
+// Do not add code here, native_mate is being removed. Any new code
+// should use gin instead.
+
 namespace mate {
 
 // Arguments is a wrapper around v8::FunctionCallbackInfo that integrates

+ 4 - 0
native_mate/native_mate/function_template.h

@@ -13,6 +13,10 @@
 #include "native_mate/wrappable_base.h"
 #include "v8/include/v8.h"
 
+// =============================== NOTICE ===============================
+// Do not add code here, native_mate is being removed. Any new code
+// should use gin instead.
+
 namespace mate {
 
 enum CreateFunctionTemplateFlags {

+ 1 - 1
shell/browser/api/atom_api_app.cc

@@ -42,7 +42,7 @@
 #include "shell/browser/relauncher.h"
 #include "shell/common/application_info.h"
 #include "shell/common/atom_command_line.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/native_mate_converters/gurl_converter.h"
 #include "shell/common/native_mate_converters/image_converter.h"

+ 1 - 1
shell/browser/api/atom_api_app.h

@@ -28,7 +28,7 @@
 #include "shell/browser/browser.h"
 #include "shell/browser/browser_observer.h"
 #include "shell/common/error_util.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/promise_util.h"
 
 #if defined(USE_NSS_CERTS)

+ 1 - 1
shell/browser/api/atom_api_auto_updater.cc

@@ -11,7 +11,7 @@
 #include "shell/browser/native_window.h"
 #include "shell/browser/window_list.h"
 #include "shell/common/api/event_emitter_caller.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/node_includes.h"
 
 namespace mate {

+ 1 - 1
shell/browser/api/atom_api_browser_window.cc

@@ -19,7 +19,7 @@
 #include "shell/browser/window_list.h"
 #include "shell/common/api/constructor.h"
 #include "shell/common/color_util.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/value_converter.h"
 #include "shell/common/node_includes.h"
 #include "shell/common/options_switches.h"

+ 1 - 1
shell/browser/api/atom_api_content_tracing.cc

@@ -12,7 +12,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "content/public/browser/tracing_controller.h"
 #include "native_mate/dictionary.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/native_mate_converters/value_converter.h"
 #include "shell/common/node_includes.h"

+ 1 - 1
shell/browser/api/atom_api_cookies.cc

@@ -20,7 +20,7 @@
 #include "net/cookies/cookie_util.h"
 #include "shell/browser/atom_browser_context.h"
 #include "shell/browser/cookie_change_notifier.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/gurl_converter.h"
 #include "shell/common/native_mate_converters/value_converter.h"
 

+ 1 - 1
shell/browser/api/atom_api_debugger.cc

@@ -13,7 +13,7 @@
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/web_contents.h"
 #include "native_mate/dictionary.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/value_converter.h"
 #include "shell/common/node_includes.h"
 

+ 12 - 28
shell/browser/api/atom_api_dialog.cc

@@ -6,15 +6,15 @@
 #include <utility>
 #include <vector>
 
-#include "gin/dictionary.h"
 #include "shell/browser/ui/certificate_trust.h"
 #include "shell/browser/ui/file_dialog.h"
 #include "shell/browser/ui/message_box.h"
-#include "shell/common/api/gin_utils.h"
+#include "shell/common/gin_converters/callback_converter.h"
 #include "shell/common/gin_converters/file_dialog_converter.h"
 #include "shell/common/gin_converters/message_box_converter.h"
 #include "shell/common/gin_converters/native_window_converter.h"
 #include "shell/common/gin_converters/net_converter.h"
+#include "shell/common/gin_helper/dictionary.h"
 #include "shell/common/node_includes.h"
 #include "shell/common/promise_util.h"
 
@@ -87,33 +87,17 @@ void Initialize(v8::Local<v8::Object> exports,
                 v8::Local<v8::Context> context,
                 void* priv) {
   v8::Isolate* isolate = context->GetIsolate();
-  gin::Dictionary dict(isolate, exports);
-  dict.Set("showMessageBoxSync",
-           gin::ConvertCallbackToV8Leaked(
-               isolate, base::BindRepeating(&ShowMessageBoxSync)));
-  dict.Set("showMessageBox",
-           gin::ConvertCallbackToV8Leaked(
-               isolate, base::BindRepeating(&ShowMessageBox)));
-  dict.Set("showErrorBox",
-           gin::ConvertCallbackToV8Leaked(
-               isolate, base::BindRepeating(&electron::ShowErrorBox)));
-  dict.Set("showOpenDialogSync",
-           gin::ConvertCallbackToV8Leaked(
-               isolate, base::BindRepeating(&ShowOpenDialogSync)));
-  dict.Set("showOpenDialog",
-           gin::ConvertCallbackToV8Leaked(
-               isolate, base::BindRepeating(&ShowOpenDialog)));
-  dict.Set("showSaveDialogSync",
-           gin::ConvertCallbackToV8Leaked(
-               isolate, base::BindRepeating(&ShowSaveDialogSync)));
-  dict.Set("showSaveDialog",
-           gin::ConvertCallbackToV8Leaked(
-               isolate, base::BindRepeating(&ShowSaveDialog)));
+  gin_helper::Dictionary dict(isolate, exports);
+  dict.SetMethod("showMessageBoxSync", &ShowMessageBoxSync);
+  dict.SetMethod("showMessageBox", &ShowMessageBox);
+  dict.SetMethod("showErrorBox", &electron::ShowErrorBox);
+  dict.SetMethod("showOpenDialogSync", &ShowOpenDialogSync);
+  dict.SetMethod("showOpenDialog", &ShowOpenDialog);
+  dict.SetMethod("showSaveDialogSync", &ShowSaveDialogSync);
+  dict.SetMethod("showSaveDialog", &ShowSaveDialog);
 #if defined(OS_MACOSX) || defined(OS_WIN)
-  dict.Set("showCertificateTrustDialog",
-           gin::ConvertCallbackToV8Leaked(
-               isolate,
-               base::BindRepeating(&certificate_trust::ShowCertificateTrust)));
+  dict.SetMethod("showCertificateTrustDialog",
+                 &certificate_trust::ShowCertificateTrust);
 #endif
 }
 

+ 1 - 1
shell/browser/api/atom_api_download_item.cc

@@ -11,7 +11,7 @@
 #include "native_mate/dictionary.h"
 #include "net/base/filename_util.h"
 #include "shell/browser/atom_browser_main_parts.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/file_dialog_converter.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/native_mate_converters/gurl_converter.h"

+ 1 - 1
shell/browser/api/atom_api_global_shortcut.cc

@@ -12,7 +12,7 @@
 #include "native_mate/dictionary.h"
 #include "shell/browser/api/atom_api_system_preferences.h"
 #include "shell/common/native_mate_converters/accelerator_converter.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/node_includes.h"
 
 #if defined(OS_MACOSX)

+ 1 - 1
shell/browser/api/atom_api_in_app_purchase.cc

@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "native_mate/dictionary.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/node_includes.h"
 
 namespace mate {

+ 1 - 1
shell/browser/api/atom_api_menu.cc

@@ -11,7 +11,7 @@
 #include "native_mate/object_template_builder.h"
 #include "shell/browser/native_window.h"
 #include "shell/common/native_mate_converters/accelerator_converter.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/image_converter.h"
 #include "shell/common/native_mate_converters/string16_converter.h"
 #include "shell/common/node_includes.h"

+ 1 - 1
shell/browser/api/atom_api_net_log.cc

@@ -16,7 +16,7 @@
 #include "native_mate/handle.h"
 #include "shell/browser/atom_browser_context.h"
 #include "shell/browser/net/system_network_context_manager.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/node_includes.h"
 

+ 1 - 1
shell/browser/api/atom_api_power_monitor.cc

@@ -8,7 +8,7 @@
 #include "base/power_monitor/power_monitor_device_source.h"
 #include "native_mate/dictionary.h"
 #include "shell/browser/browser.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/node_includes.h"
 
 namespace mate {

+ 1 - 1
shell/browser/api/atom_api_session.cc

@@ -53,7 +53,7 @@
 #include "shell/browser/media/media_device_id_salt.h"
 #include "shell/browser/net/cert_verifier_client.h"
 #include "shell/browser/session_preferences.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/content_converter.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/native_mate_converters/gurl_converter.h"

+ 1 - 1
shell/browser/api/atom_api_system_preferences.cc

@@ -5,7 +5,7 @@
 #include "shell/browser/api/atom_api_system_preferences.h"
 
 #include "native_mate/dictionary.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/value_converter.h"
 #include "shell/common/node_includes.h"
 #include "ui/gfx/animation/animation.h"

+ 1 - 1
shell/browser/api/atom_api_top_level_window.cc

@@ -16,7 +16,7 @@
 #include "shell/browser/api/atom_api_view.h"
 #include "shell/browser/api/atom_api_web_contents.h"
 #include "shell/common/color_util.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/native_mate_converters/gfx_converter.h"
 #include "shell/common/native_mate_converters/image_converter.h"

+ 1 - 1
shell/browser/api/atom_api_web_request_ns.cc

@@ -16,7 +16,7 @@
 #include "shell/browser/api/atom_api_session.h"
 #include "shell/browser/api/atom_api_web_contents.h"
 #include "shell/browser/atom_browser_context.h"
-#include "shell/common/gin_converters/callback_converter_gin_adapter.h"
+#include "shell/common/gin_converters/callback_converter.h"
 #include "shell/common/gin_converters/gurl_converter.h"
 #include "shell/common/gin_converters/net_converter.h"
 #include "shell/common/gin_converters/std_converter.h"

+ 1 - 1
shell/browser/atom_download_manager_delegate.cc

@@ -23,7 +23,7 @@
 #include "shell/browser/native_window.h"
 #include "shell/browser/ui/file_dialog.h"
 #include "shell/browser/web_contents_preferences.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/options_switches.h"
 
 namespace electron {

+ 1 - 1
shell/browser/net/node_stream_loader.cc

@@ -8,7 +8,7 @@
 
 #include "mojo/public/cpp/system/string_data_source.h"
 #include "shell/common/api/event_emitter_caller.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 
 #include "shell/common/node_includes.h"
 

+ 1 - 1
shell/common/api/atom_api_asar.cc

@@ -11,7 +11,7 @@
 #include "native_mate/object_template_builder.h"
 #include "native_mate/wrappable.h"
 #include "shell/common/asar/archive.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/node_includes.h"
 #include "third_party/electron_node/src/node_native_module_env.h"

+ 20 - 17
shell/common/api/atom_api_crash_reporter.cc

@@ -7,9 +7,9 @@
 
 #include "base/bind.h"
 #include "gin/data_object_builder.h"
-#include "gin/dictionary.h"
 #include "shell/common/crash_reporter/crash_reporter.h"
-#include "shell/common/gin_util.h"
+#include "shell/common/gin_converters/callback_converter.h"
+#include "shell/common/gin_helper/dictionary.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/native_mate_converters/map_converter.h"
 
@@ -41,23 +41,26 @@ void Initialize(v8::Local<v8::Object> exports,
                 v8::Local<v8::Value> unused,
                 v8::Local<v8::Context> context,
                 void* priv) {
-  using gin_util::SetMethod;
   auto reporter = base::Unretained(CrashReporter::GetInstance());
-  SetMethod(exports, "start",
-            base::BindRepeating(&CrashReporter::Start, reporter));
-  SetMethod(exports, "addExtraParameter",
-            base::BindRepeating(&CrashReporter::AddExtraParameter, reporter));
-  SetMethod(
-      exports, "removeExtraParameter",
+  gin_helper::Dictionary dict(context->GetIsolate(), exports);
+  dict.SetMethod("start", base::BindRepeating(&CrashReporter::Start, reporter));
+  dict.SetMethod(
+      "addExtraParameter",
+      base::BindRepeating(&CrashReporter::AddExtraParameter, reporter));
+  dict.SetMethod(
+      "removeExtraParameter",
       base::BindRepeating(&CrashReporter::RemoveExtraParameter, reporter));
-  SetMethod(exports, "getParameters",
-            base::BindRepeating(&CrashReporter::GetParameters, reporter));
-  SetMethod(exports, "getUploadedReports",
-            base::BindRepeating(&CrashReporter::GetUploadedReports, reporter));
-  SetMethod(exports, "setUploadToServer",
-            base::BindRepeating(&CrashReporter::SetUploadToServer, reporter));
-  SetMethod(exports, "getUploadToServer",
-            base::BindRepeating(&CrashReporter::GetUploadToServer, reporter));
+  dict.SetMethod("getParameters",
+                 base::BindRepeating(&CrashReporter::GetParameters, reporter));
+  dict.SetMethod(
+      "getUploadedReports",
+      base::BindRepeating(&CrashReporter::GetUploadedReports, reporter));
+  dict.SetMethod(
+      "setUploadToServer",
+      base::BindRepeating(&CrashReporter::SetUploadToServer, reporter));
+  dict.SetMethod(
+      "getUploadToServer",
+      base::BindRepeating(&CrashReporter::GetUploadToServer, reporter));
 }
 
 }  // namespace

+ 1 - 1
shell/common/api/atom_api_shell.cc

@@ -5,7 +5,7 @@
 #include <string>
 
 #include "native_mate/dictionary.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/file_path_converter.h"
 #include "shell/common/native_mate_converters/gurl_converter.h"
 #include "shell/common/native_mate_converters/string16_converter.h"

+ 0 - 27
shell/common/api/gin_utils.h

@@ -1,27 +0,0 @@
-// Copyright (c) 2019 GitHub, Inc.
-// Use of this source code is governed by the MIT license that can be
-// found in the LICENSE file.
-
-#ifndef SHELL_COMMON_API_GIN_UTILS_H_
-#define SHELL_COMMON_API_GIN_UTILS_H_
-
-#include "gin/function_template.h"
-
-namespace gin {
-
-// NOTE: V8 caches FunctionTemplates. Therefore it is user's responsibility
-// to ensure this function is called for one type only ONCE in the program's
-// whole lifetime, otherwise we would have memory leak.
-template <typename Sig>
-v8::Local<v8::Function> ConvertCallbackToV8Leaked(
-    v8::Isolate* isolate,
-    const base::RepeatingCallback<Sig>& callback) {
-  // LOG(WARNING) << "Leaky conversion from callback to V8 triggered.";
-  return gin::CreateFunctionTemplate(isolate, callback)
-      ->GetFunction(isolate->GetCurrentContext())
-      .ToLocalChecked();
-}
-
-}  // namespace gin
-
-#endif  // SHELL_COMMON_API_GIN_UTILS_H_

+ 1 - 1
shell/common/deprecate_util.cc

@@ -7,7 +7,7 @@
 #include "base/callback.h"
 #include "native_mate/converter.h"
 #include "native_mate/dictionary.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 
 namespace electron {
 

+ 59 - 0
shell/common/gin_converters/callback_converter.h

@@ -0,0 +1,59 @@
+// Copyright (c) 2019 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef SHELL_COMMON_GIN_CONVERTERS_CALLBACK_CONVERTER_H_
+#define SHELL_COMMON_GIN_CONVERTERS_CALLBACK_CONVERTER_H_
+
+#include <utility>
+
+#include "base/callback_helpers.h"
+#include "shell/common/gin_helper/callback.h"
+
+namespace gin {
+
+template <typename Sig>
+struct Converter<base::RepeatingCallback<Sig>> {
+  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
+                                   const base::RepeatingCallback<Sig>& val) {
+    // We don't use CreateFunctionTemplate here because it creates a new
+    // FunctionTemplate everytime, which is cached by V8 and causes leaks.
+    auto translater =
+        base::Bind(&gin_helper::NativeFunctionInvoker<Sig>::Go, val);
+    // To avoid memory leak, we ensure that the callback can only be called
+    // for once.
+    return gin_helper::CreateFunctionFromTranslater(isolate, translater, true);
+  }
+  static bool FromV8(v8::Isolate* isolate,
+                     v8::Local<v8::Value> val,
+                     base::RepeatingCallback<Sig>* out) {
+    if (!val->IsFunction())
+      return false;
+
+    *out = base::BindRepeating(&gin_helper::V8FunctionInvoker<Sig>::Go, isolate,
+                               gin_helper::SafeV8Function(isolate, val));
+    return true;
+  }
+};
+
+template <typename Sig>
+struct Converter<base::OnceCallback<Sig>> {
+  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
+                                   base::OnceCallback<Sig> in) {
+    return gin::ConvertToV8(isolate,
+                            base::AdaptCallbackForRepeating(std::move(in)));
+  }
+  static bool FromV8(v8::Isolate* isolate,
+                     v8::Local<v8::Value> val,
+                     base::OnceCallback<Sig>* out) {
+    if (!val->IsFunction())
+      return false;
+    *out = base::BindOnce(&gin_helper::V8FunctionInvoker<Sig>::Go, isolate,
+                          gin_helper::SafeV8Function(isolate, val));
+    return true;
+  }
+};
+
+}  // namespace gin
+
+#endif  // SHELL_COMMON_GIN_CONVERTERS_CALLBACK_CONVERTER_H_

+ 0 - 44
shell/common/gin_converters/callback_converter_gin_adapter.h

@@ -1,44 +0,0 @@
-// Copyright (c) 2019 GitHub, Inc.
-// Use of this source code is governed by the MIT license that can be
-// found in the LICENSE file.
-
-#ifndef SHELL_COMMON_GIN_CONVERTERS_CALLBACK_CONVERTER_GIN_ADAPTER_H_
-#define SHELL_COMMON_GIN_CONVERTERS_CALLBACK_CONVERTER_GIN_ADAPTER_H_
-
-#include "gin/converter.h"
-#include "shell/common/native_mate_converters/once_callback.h"
-
-// TODO(zcbenz): Move the implementations from native_mate_converters to here.
-
-namespace gin {
-
-template <typename Sig>
-struct Converter<base::RepeatingCallback<Sig>> {
-  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
-                                   const base::RepeatingCallback<Sig>& in) {
-    return mate::ConvertToV8(isolate, in);
-  }
-  static bool FromV8(v8::Isolate* isolate,
-                     v8::Local<v8::Value> val,
-                     base::RepeatingCallback<Sig>* out) {
-    return mate::ConvertFromV8(isolate, val, out);
-  }
-};
-
-template <typename Sig>
-struct Converter<base::OnceCallback<Sig>> {
-  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
-                                   base::OnceCallback<Sig> in) {
-    return mate::ConvertToV8(isolate, in);
-  }
-
-  static bool FromV8(v8::Isolate* isolate,
-                     v8::Local<v8::Value> val,
-                     base::OnceCallback<Sig>* out) {
-    return mate::ConvertFromV8(isolate, val, out);
-  }
-};
-
-}  // namespace gin
-
-#endif  // SHELL_COMMON_GIN_CONVERTERS_CALLBACK_CONVERTER_GIN_ADAPTER_H_

+ 17 - 23
shell/common/native_mate_converters/callback.cc → shell/common/gin_helper/callback.cc

@@ -1,18 +1,13 @@
-// Copyright (c) 2015 GitHub, Inc. All rights reserved.
+// Copyright (c) 2019 GitHub, Inc. All rights reserved.
 // Use of this source code is governed by the MIT license that can be
 // found in the LICENSE file.
 
-#include "shell/common/native_mate_converters/callback.h"
-#include "base/stl_util.h"
-#include "content/public/browser/browser_thread.h"
-
-#include "native_mate/dictionary.h"
-
-using content::BrowserThread;
+#include "shell/common/gin_helper/callback.h"
 
-namespace mate {
+#include "content/public/browser/browser_thread.h"
+#include "gin/dictionary.h"
 
-namespace internal {
+namespace gin_helper {
 
 namespace {
 
@@ -41,7 +36,7 @@ v8::Persistent<v8::FunctionTemplate> g_call_translater;
 
 void CallTranslater(v8::Local<v8::External> external,
                     v8::Local<v8::Object> state,
-                    mate::Arguments* args) {
+                    gin::Arguments* args) {
   // Whether the callback should only be called for once.
   v8::Isolate* isolate = args->isolate();
   auto context = isolate->GetCurrentContext();
@@ -52,7 +47,7 @@ void CallTranslater(v8::Local<v8::External> external,
   if (one_time) {
     auto called_symbol = mate::StringToSymbol(isolate, "called");
     if (state->Has(context, called_symbol).ToChecked()) {
-      args->ThrowError("callback can only be called for once");
+      args->ThrowTypeError("callback can only be called for once");
       return;
     } else {
       state->Set(context, called_symbol, v8::Boolean::New(isolate, true))
@@ -74,9 +69,10 @@ void CallTranslater(v8::Local<v8::External> external,
 struct DeleteOnUIThread {
   template <typename T>
   static void Destruct(const T* x) {
-    if (Locker::IsBrowserProcess() &&
-        !BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-      BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, x);
+    if (mate::Locker::IsBrowserProcess() &&
+        !content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
+      content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE,
+                                         x);
     } else {
       delete x;
     }
@@ -124,21 +120,21 @@ v8::Local<v8::Value> CreateFunctionFromTranslater(v8::Isolate* isolate,
                                                   bool one_time) {
   // The FunctionTemplate is cached.
   if (g_call_translater.IsEmpty())
-    g_call_translater.Reset(isolate,
-                            mate::CreateFunctionTemplate(
-                                isolate, base::BindRepeating(&CallTranslater)));
+    g_call_translater.Reset(
+        isolate,
+        CreateFunctionTemplate(isolate, base::BindRepeating(&CallTranslater)));
 
   v8::Local<v8::FunctionTemplate> call_translater =
       v8::Local<v8::FunctionTemplate>::New(isolate, g_call_translater);
   auto* holder = new TranslaterHolder(isolate);
   holder->translater = translater;
-  Dictionary state = mate::Dictionary::CreateEmpty(isolate);
+  gin::Dictionary state = gin::Dictionary::CreateEmpty(isolate);
   if (one_time)
     state.Set("oneTime", true);
   auto context = isolate->GetCurrentContext();
   return BindFunctionWith(
       isolate, context, call_translater->GetFunction(context).ToLocalChecked(),
-      holder->handle.Get(isolate), state.GetHandle());
+      holder->handle.Get(isolate), gin::ConvertToV8(isolate, state));
 }
 
 // func.bind(func, arg1).
@@ -158,6 +154,4 @@ v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
       .ToLocalChecked();
 }
 
-}  // namespace internal
-
-}  // namespace mate
+}  // namespace gin_helper

+ 163 - 0
shell/common/gin_helper/callback.h

@@ -0,0 +1,163 @@
+// Copyright (c) 2019 GitHub, Inc. All rights reserved.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef SHELL_COMMON_GIN_HELPER_CALLBACK_H_
+#define SHELL_COMMON_GIN_HELPER_CALLBACK_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "shell/common/api/locker.h"
+#include "shell/common/gin_helper/function_template.h"
+
+// Implements safe convertions between JS functions and base::Callback.
+
+namespace gin {
+
+// Make it possible to convert move-only types.
+template <typename T>
+v8::Local<v8::Value> ConvertToV8(v8::Isolate* isolate, T&& input) {
+  return Converter<typename std::remove_reference<T>::type>::ToV8(
+      isolate, std::move(input));
+}
+
+}  // namespace gin
+
+namespace gin_helper {
+
+template <typename T>
+class RefCountedGlobal;
+
+// Manages the V8 function with RAII.
+class SafeV8Function {
+ public:
+  SafeV8Function(v8::Isolate* isolate, v8::Local<v8::Value> value);
+  SafeV8Function(const SafeV8Function& other);
+  ~SafeV8Function();
+
+  bool IsAlive() const;
+  v8::Local<v8::Function> NewHandle(v8::Isolate* isolate) const;
+
+ private:
+  scoped_refptr<RefCountedGlobal<v8::Function>> v8_function_;
+};
+
+// Helper to invoke a V8 function with C++ parameters.
+template <typename Sig>
+struct V8FunctionInvoker {};
+
+template <typename... ArgTypes>
+struct V8FunctionInvoker<v8::Local<v8::Value>(ArgTypes...)> {
+  static v8::Local<v8::Value> Go(v8::Isolate* isolate,
+                                 const SafeV8Function& function,
+                                 ArgTypes... raw) {
+    mate::Locker locker(isolate);
+    v8::EscapableHandleScope handle_scope(isolate);
+    if (!function.IsAlive())
+      return v8::Null(isolate);
+    v8::MicrotasksScope script_scope(isolate,
+                                     v8::MicrotasksScope::kRunMicrotasks);
+    v8::Local<v8::Function> holder = function.NewHandle(isolate);
+    v8::Local<v8::Context> context = holder->CreationContext();
+    v8::Context::Scope context_scope(context);
+    std::vector<v8::Local<v8::Value>> args{
+        gin::ConvertToV8(isolate, std::forward<ArgTypes>(raw))...};
+    v8::MaybeLocal<v8::Value> ret = holder->Call(
+        context, holder, args.size(), args.empty() ? nullptr : &args.front());
+    if (ret.IsEmpty())
+      return v8::Undefined(isolate);
+    else
+      return handle_scope.Escape(ret.ToLocalChecked());
+  }
+};
+
+template <typename... ArgTypes>
+struct V8FunctionInvoker<void(ArgTypes...)> {
+  static void Go(v8::Isolate* isolate,
+                 const SafeV8Function& function,
+                 ArgTypes... raw) {
+    mate::Locker locker(isolate);
+    v8::HandleScope handle_scope(isolate);
+    if (!function.IsAlive())
+      return;
+    v8::MicrotasksScope script_scope(isolate,
+                                     v8::MicrotasksScope::kRunMicrotasks);
+    v8::Local<v8::Function> holder = function.NewHandle(isolate);
+    v8::Local<v8::Context> context = holder->CreationContext();
+    v8::Context::Scope context_scope(context);
+    std::vector<v8::Local<v8::Value>> args{
+        gin::ConvertToV8(isolate, std::forward<ArgTypes>(raw))...};
+    holder
+        ->Call(context, holder, args.size(),
+               args.empty() ? nullptr : &args.front())
+        .IsEmpty();
+  }
+};
+
+template <typename ReturnType, typename... ArgTypes>
+struct V8FunctionInvoker<ReturnType(ArgTypes...)> {
+  static ReturnType Go(v8::Isolate* isolate,
+                       const SafeV8Function& function,
+                       ArgTypes... raw) {
+    mate::Locker locker(isolate);
+    v8::HandleScope handle_scope(isolate);
+    ReturnType ret = ReturnType();
+    if (!function.IsAlive())
+      return ret;
+    v8::MicrotasksScope script_scope(isolate,
+                                     v8::MicrotasksScope::kRunMicrotasks);
+    v8::Local<v8::Function> holder = function.NewHandle(isolate);
+    v8::Local<v8::Context> context = holder->CreationContext();
+    v8::Context::Scope context_scope(context);
+    std::vector<v8::Local<v8::Value>> args{
+        gin::ConvertToV8(isolate, std::forward<ArgTypes>(raw))...};
+    v8::Local<v8::Value> result;
+    auto maybe_result = holder->Call(context, holder, args.size(),
+                                     args.empty() ? nullptr : &args.front());
+    if (maybe_result.ToLocal(&result))
+      gin::Converter<ReturnType>::FromV8(isolate, result, &ret);
+    return ret;
+  }
+};
+
+// Helper to pass a C++ funtion to JavaScript.
+using Translater = base::Callback<void(gin::Arguments* args)>;
+v8::Local<v8::Value> CreateFunctionFromTranslater(v8::Isolate* isolate,
+                                                  const Translater& translater,
+                                                  bool one_time);
+v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
+                                      v8::Local<v8::Context> context,
+                                      v8::Local<v8::Function> func,
+                                      v8::Local<v8::Value> arg1,
+                                      v8::Local<v8::Value> arg2);
+
+// Calls callback with Arguments.
+template <typename Sig>
+struct NativeFunctionInvoker {};
+
+template <typename ReturnType, typename... ArgTypes>
+struct NativeFunctionInvoker<ReturnType(ArgTypes...)> {
+  static void Go(base::Callback<ReturnType(ArgTypes...)> val,
+                 gin::Arguments* args) {
+    using Indices = typename IndicesGenerator<sizeof...(ArgTypes)>::type;
+    Invoker<Indices, ArgTypes...> invoker(args, 0);
+    if (invoker.IsOK())
+      invoker.DispatchToCallback(val);
+  }
+};
+
+// Convert a callback to V8 without the call number limitation, this can easily
+// cause memory leaks so use it with caution.
+template <typename Sig>
+v8::Local<v8::Value> CallbackToV8Leaked(
+    v8::Isolate* isolate,
+    const base::RepeatingCallback<Sig>& val) {
+  Translater translater = base::Bind(&NativeFunctionInvoker<Sig>::Go, val);
+  return CreateFunctionFromTranslater(isolate, translater, false);
+}
+
+}  // namespace gin_helper
+
+#endif  // SHELL_COMMON_GIN_HELPER_CALLBACK_H_

+ 84 - 0
shell/common/gin_helper/dictionary.h

@@ -0,0 +1,84 @@
+// Copyright (c) 2019 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef SHELL_COMMON_GIN_HELPER_DICTIONARY_H_
+#define SHELL_COMMON_GIN_HELPER_DICTIONARY_H_
+
+#include <type_traits>
+
+#include "base/bind.h"
+#include "gin/dictionary.h"
+#include "shell/common/gin_helper/function_template.h"
+
+namespace gin_helper {
+
+// Base template - used only for non-member function pointers. Other types
+// either go to one of the below specializations, or go here and fail to compile
+// because of base::Bind().
+template <typename T, typename Enable = void>
+struct CallbackTraits {
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate,
+                                                        T callback) {
+    return CreateFunctionTemplate(isolate, base::BindRepeating(callback));
+  }
+};
+
+// Specialization for base::Callback.
+template <typename T>
+struct CallbackTraits<base::Callback<T>> {
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(
+      v8::Isolate* isolate,
+      const base::RepeatingCallback<T>& callback) {
+    return CreateFunctionTemplate(isolate, callback);
+  }
+};
+
+// Specialization for member function pointers. We need to handle this case
+// specially because the first parameter for callbacks to MFP should typically
+// come from the the JavaScript "this" object the function was called on, not
+// from the first normal parameter.
+template <typename T>
+struct CallbackTraits<
+    T,
+    typename std::enable_if<std::is_member_function_pointer<T>::value>::type> {
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate,
+                                                        T callback) {
+    int flags = HolderIsFirstArgument;
+    return CreateFunctionTemplate(isolate, base::BindRepeating(callback),
+                                  flags);
+  }
+};
+
+// Adds a few more extends methods to gin::Dictionary.
+//
+// Note that as the destructor of gin::Dictionary is not virtual, and we want to
+// convert between 2 types, we must not add any member.
+class Dictionary : public gin::Dictionary {
+ public:
+  Dictionary(v8::Isolate* isolate, v8::Local<v8::Object> object)
+      : gin::Dictionary(isolate, object) {}
+
+  template <typename T>
+  bool SetMethod(base::StringPiece key, const T& callback) {
+    auto context = isolate()->GetCurrentContext();
+    auto templ = CallbackTraits<T>::CreateTemplate(isolate(), callback);
+    return GetHandle()
+        ->Set(context, gin::StringToV8(isolate(), key),
+              templ->GetFunction(context).ToLocalChecked())
+        .ToChecked();
+  }
+
+  v8::Local<v8::Object> GetHandle() const {
+    return gin::ConvertToV8(isolate(),
+                            *static_cast<const gin::Dictionary*>(this))
+        .As<v8::Object>();
+  }
+
+ private:
+  // DO NOT ADD ANY DATA MEMBER.
+};
+
+}  // namespace gin_helper
+
+#endif  // SHELL_COMMON_GIN_HELPER_DICTIONARY_H_

+ 36 - 0
shell/common/gin_helper/function_template.cc

@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE.chromium file.
+
+#include "shell/common/gin_helper/function_template.h"
+
+namespace gin_helper {
+
+CallbackHolderBase::CallbackHolderBase(v8::Isolate* isolate)
+    : v8_ref_(isolate, v8::External::New(isolate, this)) {
+  v8_ref_.SetWeak(this, &CallbackHolderBase::FirstWeakCallback,
+                  v8::WeakCallbackType::kParameter);
+}
+
+CallbackHolderBase::~CallbackHolderBase() {
+  DCHECK(v8_ref_.IsEmpty());
+}
+
+v8::Local<v8::External> CallbackHolderBase::GetHandle(v8::Isolate* isolate) {
+  return v8::Local<v8::External>::New(isolate, v8_ref_);
+}
+
+// static
+void CallbackHolderBase::FirstWeakCallback(
+    const v8::WeakCallbackInfo<CallbackHolderBase>& data) {
+  data.GetParameter()->v8_ref_.Reset();
+  data.SetSecondPassCallback(SecondWeakCallback);
+}
+
+// static
+void CallbackHolderBase::SecondWeakCallback(
+    const v8::WeakCallbackInfo<CallbackHolderBase>& data) {
+  delete data.GetParameter();
+}
+
+}  // namespace gin_helper

+ 263 - 0
shell/common/gin_helper/function_template.h

@@ -0,0 +1,263 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE.chromium file.
+
+#ifndef SHELL_COMMON_GIN_HELPER_FUNCTION_TEMPLATE_H_
+#define SHELL_COMMON_GIN_HELPER_FUNCTION_TEMPLATE_H_
+
+#include "base/callback.h"
+#include "gin/arguments.h"
+#include "shell/common/error_util.h"
+#include "shell/common/gin_helper/destroyable.h"
+
+// This file is forked from gin/function_template.h with 2 differences:
+// 1. Support for additional types of arguments.
+// 2. Support for warning using destroyed objects.
+//
+// TODO(zcbenz): We should seek to remove this file after removing native_mate.
+
+namespace gin_helper {
+
+enum CreateFunctionTemplateFlags {
+  HolderIsFirstArgument = 1 << 0,
+};
+
+template <typename T>
+struct CallbackParamTraits {
+  typedef T LocalType;
+};
+template <typename T>
+struct CallbackParamTraits<const T&> {
+  typedef T LocalType;
+};
+template <typename T>
+struct CallbackParamTraits<const T*> {
+  typedef T* LocalType;
+};
+
+// CallbackHolder and CallbackHolderBase are used to pass a base::Callback from
+// CreateFunctionTemplate through v8 (via v8::FunctionTemplate) to
+// DispatchToCallback, where it is invoked.
+
+// This simple base class is used so that we can share a single object template
+// among every CallbackHolder instance.
+class CallbackHolderBase {
+ public:
+  v8::Local<v8::External> GetHandle(v8::Isolate* isolate);
+
+ protected:
+  explicit CallbackHolderBase(v8::Isolate* isolate);
+  virtual ~CallbackHolderBase();
+
+ private:
+  static void FirstWeakCallback(
+      const v8::WeakCallbackInfo<CallbackHolderBase>& data);
+  static void SecondWeakCallback(
+      const v8::WeakCallbackInfo<CallbackHolderBase>& data);
+
+  v8::Global<v8::External> v8_ref_;
+
+  DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase);
+};
+
+template <typename Sig>
+class CallbackHolder : public CallbackHolderBase {
+ public:
+  CallbackHolder(v8::Isolate* isolate,
+                 const base::Callback<Sig>& callback,
+                 int flags)
+      : CallbackHolderBase(isolate), callback(callback), flags(flags) {}
+  base::Callback<Sig> callback;
+  int flags = 0;
+
+ private:
+  virtual ~CallbackHolder() = default;
+
+  DISALLOW_COPY_AND_ASSIGN(CallbackHolder);
+};
+
+template <typename T>
+bool GetNextArgument(gin::Arguments* args,
+                     int create_flags,
+                     bool is_first,
+                     T* result) {
+  if (is_first && (create_flags & HolderIsFirstArgument) != 0) {
+    return args->GetHolder(result);
+  } else {
+    return args->GetNext(result);
+  }
+}
+
+// For advanced use cases, we allow callers to request the unparsed Arguments
+// object and poke around in it directly.
+inline bool GetNextArgument(gin::Arguments* args,
+                            int create_flags,
+                            bool is_first,
+                            gin::Arguments** result) {
+  *result = args;
+  return true;
+}
+
+// It's common for clients to just need the isolate, so we make that easy.
+inline bool GetNextArgument(gin::Arguments* args,
+                            int create_flags,
+                            bool is_first,
+                            v8::Isolate** result) {
+  *result = args->isolate();
+  return true;
+}
+
+// Allow clients to pass a util::Error to throw errors if they
+// don't need the full gin::Arguments
+inline bool GetNextArgument(gin::Arguments* args,
+                            int create_flags,
+                            bool is_first,
+                            electron::util::ErrorThrower* result) {
+  *result = electron::util::ErrorThrower(args->isolate());
+  return true;
+}
+
+// Classes for generating and storing an argument pack of integer indices
+// (based on well-known "indices trick", see: http://goo.gl/bKKojn):
+template <size_t... indices>
+struct IndicesHolder {};
+
+template <size_t requested_index, size_t... indices>
+struct IndicesGenerator {
+  using type = typename IndicesGenerator<requested_index - 1,
+                                         requested_index - 1,
+                                         indices...>::type;
+};
+template <size_t... indices>
+struct IndicesGenerator<0, indices...> {
+  using type = IndicesHolder<indices...>;
+};
+
+// Class template for extracting and storing single argument for callback
+// at position |index|.
+template <size_t index, typename ArgType>
+struct ArgumentHolder {
+  using ArgLocalType = typename CallbackParamTraits<ArgType>::LocalType;
+
+  ArgLocalType value;
+  bool ok = false;
+
+  ArgumentHolder(gin::Arguments* args, int create_flags) {
+    v8::Local<v8::Object> holder;
+    if (index == 0 && (create_flags & HolderIsFirstArgument) &&
+        args->GetHolder(&holder) &&
+        gin_helper::Destroyable::IsDestroyed(holder)) {
+      args->ThrowTypeError("Object has been destroyed");
+      return;
+    }
+    ok = GetNextArgument(args, create_flags, index == 0, &value);
+    if (!ok) {
+      // Ideally we would include the expected c++ type in the error
+      // message which we can access via typeid(ArgType).name()
+      // however we compile with no-rtti, which disables typeid.
+      args->ThrowError();
+    }
+  }
+};
+
+// Class template for converting arguments from JavaScript to C++ and running
+// the callback with them.
+template <typename IndicesType, typename... ArgTypes>
+class Invoker {};
+
+template <size_t... indices, typename... ArgTypes>
+class Invoker<IndicesHolder<indices...>, ArgTypes...>
+    : public ArgumentHolder<indices, ArgTypes>... {
+ public:
+  // Invoker<> inherits from ArgumentHolder<> for each argument.
+  // C++ has always been strict about the class initialization order,
+  // so it is guaranteed ArgumentHolders will be initialized (and thus, will
+  // extract arguments from Arguments) in the right order.
+  Invoker(gin::Arguments* args, int create_flags)
+      : ArgumentHolder<indices, ArgTypes>(args, create_flags)..., args_(args) {
+    // GCC thinks that create_flags is going unused, even though the
+    // expansion above clearly makes use of it. Per jyasskin@, casting
+    // to void is the commonly accepted way to convince the compiler
+    // that you're actually using a parameter/varible.
+    (void)create_flags;
+  }
+
+  bool IsOK() { return And(ArgumentHolder<indices, ArgTypes>::ok...); }
+
+  template <typename ReturnType>
+  void DispatchToCallback(base::Callback<ReturnType(ArgTypes...)> callback) {
+    v8::MicrotasksScope script_scope(args_->isolate(),
+                                     v8::MicrotasksScope::kRunMicrotasks);
+    args_->Return(callback.Run(ArgumentHolder<indices, ArgTypes>::value...));
+  }
+
+  // In C++, you can declare the function foo(void), but you can't pass a void
+  // expression to foo. As a result, we must specialize the case of Callbacks
+  // that have the void return type.
+  void DispatchToCallback(base::Callback<void(ArgTypes...)> callback) {
+    v8::MicrotasksScope script_scope(args_->isolate(),
+                                     v8::MicrotasksScope::kRunMicrotasks);
+    callback.Run(ArgumentHolder<indices, ArgTypes>::value...);
+  }
+
+ private:
+  static bool And() { return true; }
+  template <typename... T>
+  static bool And(bool arg1, T... args) {
+    return arg1 && And(args...);
+  }
+
+  gin::Arguments* args_;
+};
+
+// DispatchToCallback converts all the JavaScript arguments to C++ types and
+// invokes the base::Callback.
+template <typename Sig>
+struct Dispatcher {};
+
+template <typename ReturnType, typename... ArgTypes>
+struct Dispatcher<ReturnType(ArgTypes...)> {
+  static void DispatchToCallback(
+      const v8::FunctionCallbackInfo<v8::Value>& info) {
+    gin::Arguments args(info);
+    v8::Local<v8::External> v8_holder;
+    args.GetData(&v8_holder);
+    CallbackHolderBase* holder_base =
+        reinterpret_cast<CallbackHolderBase*>(v8_holder->Value());
+
+    typedef CallbackHolder<ReturnType(ArgTypes...)> HolderT;
+    HolderT* holder = static_cast<HolderT*>(holder_base);
+
+    using Indices = typename IndicesGenerator<sizeof...(ArgTypes)>::type;
+    Invoker<Indices, ArgTypes...> invoker(&args, holder->flags);
+    if (invoker.IsOK())
+      invoker.DispatchToCallback(holder->callback);
+  }
+};
+
+// CreateFunctionTemplate creates a v8::FunctionTemplate that will create
+// JavaScript functions that execute a provided C++ function or base::Callback.
+// JavaScript arguments are automatically converted via gin::Converter, as is
+// the return value of the C++ function, if any.
+//
+// NOTE: V8 caches FunctionTemplates for a lifetime of a web page for its own
+// internal reasons, thus it is generally a good idea to cache the template
+// returned by this function.  Otherwise, repeated method invocations from JS
+// will create substantial memory leaks. See http://crbug.com/463487.
+template <typename Sig>
+v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
+    v8::Isolate* isolate,
+    const base::Callback<Sig> callback,
+    int callback_flags = 0) {
+  typedef CallbackHolder<Sig> HolderT;
+  HolderT* holder = new HolderT(isolate, callback, callback_flags);
+
+  return v8::FunctionTemplate::New(isolate,
+                                   &Dispatcher<Sig>::DispatchToCallback,
+                                   gin::ConvertToV8<v8::Local<v8::External>>(
+                                       isolate, holder->GetHandle(isolate)));
+}
+
+}  // namespace gin_helper
+
+#endif  // SHELL_COMMON_GIN_HELPER_FUNCTION_TEMPLATE_H_

+ 0 - 29
shell/common/gin_util.h

@@ -1,29 +0,0 @@
-// Copyright (c) 2018 Slack Technologies, Inc.
-// Use of this source code is governed by the MIT license that can be
-// found in the LICENSE file.
-
-#ifndef SHELL_COMMON_GIN_UTIL_H_
-#define SHELL_COMMON_GIN_UTIL_H_
-
-#include "gin/converter.h"
-#include "gin/function_template.h"
-
-namespace gin_util {
-
-template <typename T>
-bool SetMethod(v8::Local<v8::Object> recv,
-               base::StringPiece key,
-               const T& callback) {
-  v8::Isolate* isolate = v8::Isolate::GetCurrent();
-  auto context = isolate->GetCurrentContext();
-  return recv
-      ->Set(context, gin::StringToV8(isolate, key),
-            gin::CreateFunctionTemplate(isolate, callback)
-                ->GetFunction(context)
-                .ToLocalChecked())
-      .ToChecked();
-}
-
-}  // namespace gin_util
-
-#endif  // SHELL_COMMON_GIN_UTIL_H_

+ 163 - 0
shell/common/native_mate_converters/callback_converter_deprecated.cc

@@ -0,0 +1,163 @@
+// Copyright (c) 2015 GitHub, Inc. All rights reserved.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
+#include "base/stl_util.h"
+#include "content/public/browser/browser_thread.h"
+
+#include "native_mate/dictionary.h"
+
+using content::BrowserThread;
+
+namespace mate {
+
+namespace internal {
+
+namespace {
+
+struct TranslaterHolder {
+  explicit TranslaterHolder(v8::Isolate* isolate)
+      : handle(isolate, v8::External::New(isolate, this)) {
+    handle.SetWeak(this, &GC, v8::WeakCallbackType::kFinalizer);
+  }
+  ~TranslaterHolder() {
+    if (!handle.IsEmpty()) {
+      handle.ClearWeak();
+      handle.Reset();
+    }
+  }
+
+  static void GC(const v8::WeakCallbackInfo<TranslaterHolder>& data) {
+    delete data.GetParameter();
+  }
+
+  v8::Global<v8::External> handle;
+  Translater translater;
+};
+
+// Cached JavaScript version of |CallTranslater|.
+v8::Persistent<v8::FunctionTemplate> g_call_translater;
+
+void CallTranslater(v8::Local<v8::External> external,
+                    v8::Local<v8::Object> state,
+                    mate::Arguments* args) {
+  // Whether the callback should only be called for once.
+  v8::Isolate* isolate = args->isolate();
+  auto context = isolate->GetCurrentContext();
+  bool one_time =
+      state->Has(context, mate::StringToSymbol(isolate, "oneTime")).ToChecked();
+
+  // Check if the callback has already been called.
+  if (one_time) {
+    auto called_symbol = mate::StringToSymbol(isolate, "called");
+    if (state->Has(context, called_symbol).ToChecked()) {
+      args->ThrowError("callback can only be called for once");
+      return;
+    } else {
+      state->Set(context, called_symbol, v8::Boolean::New(isolate, true))
+          .ToChecked();
+    }
+  }
+
+  TranslaterHolder* holder = static_cast<TranslaterHolder*>(external->Value());
+  holder->translater.Run(args);
+
+  // Free immediately for one-time callback.
+  if (one_time)
+    delete holder;
+}
+
+}  // namespace
+
+// Destroy the class on UI thread when possible.
+struct DeleteOnUIThread {
+  template <typename T>
+  static void Destruct(const T* x) {
+    if (Locker::IsBrowserProcess() &&
+        !BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+      BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, x);
+    } else {
+      delete x;
+    }
+  }
+};
+
+// Like v8::Global, but ref-counted.
+template <typename T>
+class RefCountedGlobal
+    : public base::RefCountedThreadSafe<RefCountedGlobal<T>, DeleteOnUIThread> {
+ public:
+  RefCountedGlobal(v8::Isolate* isolate, v8::Local<v8::Value> value)
+      : handle_(isolate, v8::Local<T>::Cast(value)) {}
+
+  bool IsAlive() const { return !handle_.IsEmpty(); }
+
+  v8::Local<T> NewHandle(v8::Isolate* isolate) const {
+    return v8::Local<T>::New(isolate, handle_);
+  }
+
+ private:
+  v8::Global<T> handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(RefCountedGlobal);
+};
+
+SafeV8Function::SafeV8Function(v8::Isolate* isolate, v8::Local<v8::Value> value)
+    : v8_function_(new RefCountedGlobal<v8::Function>(isolate, value)) {}
+
+SafeV8Function::SafeV8Function(const SafeV8Function& other)
+    : v8_function_(other.v8_function_) {}
+
+SafeV8Function::~SafeV8Function() {}
+
+bool SafeV8Function::IsAlive() const {
+  return v8_function_.get() && v8_function_->IsAlive();
+}
+
+v8::Local<v8::Function> SafeV8Function::NewHandle(v8::Isolate* isolate) const {
+  return v8_function_->NewHandle(isolate);
+}
+
+v8::Local<v8::Value> CreateFunctionFromTranslater(v8::Isolate* isolate,
+                                                  const Translater& translater,
+                                                  bool one_time) {
+  // The FunctionTemplate is cached.
+  if (g_call_translater.IsEmpty())
+    g_call_translater.Reset(isolate,
+                            mate::CreateFunctionTemplate(
+                                isolate, base::BindRepeating(&CallTranslater)));
+
+  v8::Local<v8::FunctionTemplate> call_translater =
+      v8::Local<v8::FunctionTemplate>::New(isolate, g_call_translater);
+  auto* holder = new TranslaterHolder(isolate);
+  holder->translater = translater;
+  Dictionary state = mate::Dictionary::CreateEmpty(isolate);
+  if (one_time)
+    state.Set("oneTime", true);
+  auto context = isolate->GetCurrentContext();
+  return BindFunctionWith(
+      isolate, context, call_translater->GetFunction(context).ToLocalChecked(),
+      holder->handle.Get(isolate), state.GetHandle());
+}
+
+// func.bind(func, arg1).
+// NB(zcbenz): Using C++11 version crashes VS.
+v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
+                                      v8::Local<v8::Context> context,
+                                      v8::Local<v8::Function> func,
+                                      v8::Local<v8::Value> arg1,
+                                      v8::Local<v8::Value> arg2) {
+  v8::MaybeLocal<v8::Value> bind =
+      func->Get(context, mate::StringToV8(isolate, "bind"));
+  CHECK(!bind.IsEmpty());
+  v8::Local<v8::Function> bind_func =
+      v8::Local<v8::Function>::Cast(bind.ToLocalChecked());
+  v8::Local<v8::Value> converted[] = {func, arg1, arg2};
+  return bind_func->Call(context, func, base::size(converted), converted)
+      .ToLocalChecked();
+}
+
+}  // namespace internal
+
+}  // namespace mate

+ 7 - 3
shell/common/native_mate_converters/callback.h → shell/common/native_mate_converters/callback_converter_deprecated.h

@@ -2,8 +2,8 @@
 // Use of this source code is governed by the MIT license that can be
 // found in the LICENSE file.
 
-#ifndef SHELL_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_H_
-#define SHELL_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_H_
+#ifndef SHELL_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_CONVERTER_DEPRECATED_H_
+#define SHELL_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_CONVERTER_DEPRECATED_H_
 
 #include <utility>
 #include <vector>
@@ -16,6 +16,10 @@
 #include "native_mate/scoped_persistent.h"
 #include "shell/common/api/locker.h"
 
+// =============================== NOTICE ===============================
+// Do not add code here, native_mate is being removed. Any new code
+// should use gin instead.
+
 namespace mate {
 
 namespace internal {
@@ -178,4 +182,4 @@ v8::Local<v8::Value> CallbackToV8(v8::Isolate* isolate,
 
 }  // namespace mate
 
-#endif  // SHELL_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_H_
+#endif  // SHELL_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_CONVERTER_DEPRECATED_H_

+ 1 - 1
shell/common/native_mate_converters/content_converter.cc

@@ -13,7 +13,7 @@
 #include "shell/browser/api/atom_api_web_contents.h"
 #include "shell/browser/web_contents_permission_helper.h"
 #include "shell/common/native_mate_converters/blink_converter.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/gurl_converter.h"
 #include "shell/common/native_mate_converters/string16_converter.h"
 #include "shell/common/native_mate_converters/ui_base_types_converter.h"

+ 1 - 1
shell/common/native_mate_converters/once_callback.h

@@ -7,7 +7,7 @@
 
 #include <utility>
 
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 
 namespace mate {
 

+ 1 - 1
shell/common/promise_util.h

@@ -15,7 +15,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "native_mate/converter.h"
 #include "shell/common/api/locker.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/once_callback.h"
 
 namespace electron {

+ 1 - 1
shell/renderer/api/atom_api_web_frame.cc

@@ -18,7 +18,7 @@
 #include "shell/common/api/api.mojom.h"
 #include "shell/common/api/event_emitter_caller.h"
 #include "shell/common/native_mate_converters/blink_converter.h"
-#include "shell/common/native_mate_converters/callback.h"
+#include "shell/common/native_mate_converters/callback_converter_deprecated.h"
 #include "shell/common/native_mate_converters/gfx_converter.h"
 #include "shell/common/native_mate_converters/string16_converter.h"
 #include "shell/common/node_includes.h"