diff --git a/lib/browser/desktop-capturer.ts b/lib/browser/desktop-capturer.ts index 2797b1c9c1ac..4badb9601988 100644 --- a/lib/browser/desktop-capturer.ts +++ b/lib/browser/desktop-capturer.ts @@ -1,5 +1,3 @@ -import { EventEmitter } from 'events' - const { createDesktopCapturer } = process.electronBinding('desktop_capturer') const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b) @@ -23,21 +21,20 @@ export const getSources = (event: Electron.IpcMainEvent, options: ElectronIntern const stopRunning = () => { if (capturer) { - capturer.emit = null + delete capturer._onerror + delete capturer._onfinished capturer = null } // Remove from currentlyRunning once we resolve or reject currentlyRunning = currentlyRunning.filter(running => running.options !== options) } - const emitter = new EventEmitter() - - emitter.once('error', (event, error: string) => { + capturer._onerror = (error: string) => { stopRunning() reject(error) - }) + } - emitter.once('finished', (event, sources: Electron.DesktopCapturerSource[], fetchWindowIcons: boolean) => { + capturer._onfinished = (sources: Electron.DesktopCapturerSource[], fetchWindowIcons: boolean) => { stopRunning() resolve(sources.map(source => ({ id: source.id, @@ -46,9 +43,8 @@ export const getSources = (event: Electron.IpcMainEvent, options: ElectronIntern display_id: source.display_id, appIcon: (fetchWindowIcons && source.appIcon) ? source.appIcon.toDataURL() : null }))) - }) + } - capturer.emit = emitter.emit.bind(emitter) capturer.startHandling(options.captureWindow, options.captureScreen, options.thumbnailSize, options.fetchWindowIcons) // If the WebContents is destroyed before receiving result, just remove the diff --git a/shell/browser/api/electron_api_desktop_capturer.cc b/shell/browser/api/electron_api_desktop_capturer.cc index a536fcced624..0a0657b5e920 100644 --- a/shell/browser/api/electron_api_desktop_capturer.cc +++ b/shell/browser/api/electron_api_desktop_capturer.cc @@ -14,10 +14,11 @@ #include "chrome/browser/media/webrtc/desktop_media_list.h" #include "chrome/browser/media/webrtc/window_icon_util.h" #include "content/public/browser/desktop_capture.h" +#include "gin/object_template_builder.h" #include "shell/common/api/electron_api_native_image.h" #include "shell/common/gin_converters/gfx_converter.h" #include "shell/common/gin_helper/dictionary.h" -#include "shell/common/gin_helper/object_template_builder.h" +#include "shell/common/gin_helper/event_emitter_caller.h" #include "shell/common/node_includes.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" @@ -59,9 +60,9 @@ namespace electron { namespace api { -DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) { - Init(isolate); -} +gin::WrapperInfo DesktopCapturer::kWrapperInfo = {gin::kEmbedderNativeGin}; + +DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {} DesktopCapturer::~DesktopCapturer() = default; @@ -154,7 +155,7 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) { // |media_list_sources|. if (!webrtc::DxgiDuplicatorController::Instance()->GetDeviceNames( &device_names)) { - Emit("error", "Failed to get sources."); + gin_helper::CallMethod(this, "_onerror", "Failed to get sources."); return; } @@ -184,7 +185,8 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) { } if (!capture_window_ && !capture_screen_) - Emit("finished", captured_sources_, fetch_window_icons_); + gin_helper::CallMethod(this, "_onfinished", captured_sources_, + fetch_window_icons_); } // static @@ -192,15 +194,16 @@ gin::Handle DesktopCapturer::Create(v8::Isolate* isolate) { return gin::CreateHandle(isolate, new DesktopCapturer(isolate)); } -// static -void DesktopCapturer::BuildPrototype( - v8::Isolate* isolate, - v8::Local prototype) { - prototype->SetClassName(gin::StringToV8(isolate, "DesktopCapturer")); - gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) +gin::ObjectTemplateBuilder DesktopCapturer::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return gin::Wrappable::GetObjectTemplateBuilder(isolate) .SetMethod("startHandling", &DesktopCapturer::StartHandling); } +const char* DesktopCapturer::GetTypeName() { + return "DesktopCapturer"; +} + } // namespace api } // namespace electron diff --git a/shell/browser/api/electron_api_desktop_capturer.h b/shell/browser/api/electron_api_desktop_capturer.h index 53b5f128ee1f..3ef7c0bd1f16 100644 --- a/shell/browser/api/electron_api_desktop_capturer.h +++ b/shell/browser/api/electron_api_desktop_capturer.h @@ -12,13 +12,13 @@ #include "chrome/browser/media/webrtc/desktop_media_list_observer.h" #include "chrome/browser/media/webrtc/native_desktop_media_list.h" #include "gin/handle.h" -#include "shell/common/gin_helper/trackable_object.h" +#include "gin/wrappable.h" namespace electron { namespace api { -class DesktopCapturer : public gin_helper::TrackableObject, +class DesktopCapturer : public gin::Wrappable, public DesktopMediaListObserver { public: struct Source { @@ -32,14 +32,17 @@ class DesktopCapturer : public gin_helper::TrackableObject, static gin::Handle Create(v8::Isolate* isolate); - static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); - void StartHandling(bool capture_window, bool capture_screen, const gfx::Size& thumbnail_size, bool fetch_window_icons); + // gin::Wrappable + static gin::WrapperInfo kWrapperInfo; + gin::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + const char* GetTypeName() override; + protected: explicit DesktopCapturer(v8::Isolate* isolate); ~DesktopCapturer() override; diff --git a/shell/common/gin_helper/event_emitter_caller.h b/shell/common/gin_helper/event_emitter_caller.h index aeae06ad8cc6..5a5bdf6ad7a3 100644 --- a/shell/common/gin_helper/event_emitter_caller.h +++ b/shell/common/gin_helper/event_emitter_caller.h @@ -9,6 +9,7 @@ #include #include "gin/converter.h" +#include "gin/wrappable.h" namespace gin_helper { @@ -63,6 +64,28 @@ v8::Local CustomEmit(v8::Isolate* isolate, &converted_args); } +template +v8::Local CallMethod(v8::Isolate* isolate, + gin::Wrappable* object, + const char* method_name, + Args&&... args) { + v8::HandleScope scope(isolate); + v8::Local v8_object; + if (object->GetWrapper(isolate).ToLocal(&v8_object)) + return CustomEmit(isolate, v8_object, method_name, + std::forward(args)...); + else + return v8::Local(); +} + +template +v8::Local CallMethod(gin::Wrappable* object, + const char* method_name, + Args&&... args) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return CallMethod(isolate, object, method_name, std::forward(args)...); +} + } // namespace gin_helper #endif // SHELL_COMMON_GIN_HELPER_EVENT_EMITTER_CALLER_H_ diff --git a/typings/internal-electron.d.ts b/typings/internal-electron.d.ts index 7bb6defcda3d..2b2c8bacedf0 100644 --- a/typings/internal-electron.d.ts +++ b/typings/internal-electron.d.ts @@ -94,7 +94,8 @@ declare namespace ElectronInternal { interface DesktopCapturer { startHandling(captureWindow: boolean, captureScreen: boolean, thumbnailSize: Electron.Size, fetchWindowIcons: boolean): void; - emit: typeof NodeJS.EventEmitter.prototype.emit | null; + _onerror: (error: string) => void; + _onfinished: (sources: Electron.DesktopCapturerSource[], fetchWindowIcons: boolean) => void; } interface GetSourcesOptions {