Browse Source

refactor: only access memory coordinator interface from browser process (#31295) (#31303)

Refs https://chromium-review.googlesource.com/c/chromium/src/+/3174305
Robo 3 years ago
parent
commit
9c54bf7973

+ 4 - 0
lib/browser/rpc-server.ts

@@ -39,6 +39,10 @@ ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_LAST_WEB_PREFERENCES, function (
   return event.sender.getLastWebPreferences();
 });
 
+ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO, function (event) {
+  return event.sender._getProcessMemoryInfo();
+});
+
 // Methods not listed in this set are called directly in the renderer process.
 const allowedClipboardMethods = (() => {
   switch (process.platform) {

+ 1 - 0
lib/common/ipc-messages.ts

@@ -4,6 +4,7 @@ export const enum IPC_MESSAGES {
   BROWSER_PRELOAD_ERROR = 'BROWSER_PRELOAD_ERROR',
   BROWSER_SANDBOX_LOAD = 'BROWSER_SANDBOX_LOAD',
   BROWSER_WINDOW_CLOSE = 'BROWSER_WINDOW_CLOSE',
+  BROWSER_GET_PROCESS_MEMORY_INFO = 'BROWSER_GET_PROCESS_MEMORY_INFO',
 
   GUEST_INSTANCE_VISIBILITY_CHANGE = 'GUEST_INSTANCE_VISIBILITY_CHANGE',
 

+ 4 - 0
lib/renderer/init.ts

@@ -59,6 +59,10 @@ v8Util.setHiddenValue(global, 'ipcNative', {
   }
 });
 
+process.getProcessMemoryInfo = () => {
+  return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
+};
+
 // Use electron module after everything is ready.
 const { webFrameInit } = require('@electron/internal/renderer/web-frame-init') as typeof webFrameInitModule;
 webFrameInit();

+ 4 - 0
lib/sandboxed_renderer/init.ts

@@ -86,6 +86,10 @@ Object.assign(preloadProcess, processProps);
 Object.assign(process, binding.process);
 Object.assign(process, processProps);
 
+process.getProcessMemoryInfo = preloadProcess.getProcessMemoryInfo = () => {
+  return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
+};
+
 Object.defineProperty(preloadProcess, 'noDeprecation', {
   get () {
     return process.noDeprecation;

+ 23 - 0
shell/browser/api/electron_api_web_contents.cc

@@ -72,6 +72,7 @@
 #include "ppapi/buildflags/buildflags.h"
 #include "printing/buildflags/buildflags.h"
 #include "printing/print_job_constants.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "shell/browser/api/electron_api_browser_window.h"
 #include "shell/browser/api/electron_api_debugger.h"
@@ -99,6 +100,7 @@
 #include "shell/browser/web_view_guest_delegate.h"
 #include "shell/browser/web_view_manager.h"
 #include "shell/common/api/electron_api_native_image.h"
+#include "shell/common/api/electron_bindings.h"
 #include "shell/common/color_util.h"
 #include "shell/common/electron_constants.h"
 #include "shell/common/gin_converters/base_converter.h"
@@ -3251,6 +3253,26 @@ void WebContents::SetImageAnimationPolicy(const std::string& new_policy) {
   web_contents()->OnWebPreferencesChanged();
 }
 
+v8::Local<v8::Promise> WebContents::GetProcessMemoryInfo(v8::Isolate* isolate) {
+  gin_helper::Promise<gin_helper::Dictionary> promise(isolate);
+  v8::Local<v8::Promise> handle = promise.GetHandle();
+
+  auto* frame_host = web_contents()->GetMainFrame();
+  if (!frame_host) {
+    promise.RejectWithErrorMessage("Failed to create memory dump");
+    return handle;
+  }
+
+  auto pid = frame_host->GetProcess()->GetProcess().Pid();
+  v8::Global<v8::Context> context(isolate, isolate->GetCurrentContext());
+  memory_instrumentation::MemoryInstrumentation::GetInstance()
+      ->RequestGlobalDumpForPid(
+          pid, std::vector<std::string>(),
+          base::BindOnce(&ElectronBindings::DidReceiveMemoryDump,
+                         std::move(context), std::move(promise), pid));
+  return handle;
+}
+
 v8::Local<v8::Promise> WebContents::TakeHeapSnapshot(
     v8::Isolate* isolate,
     const base::FilePath& file_path) {
@@ -3882,6 +3904,7 @@ v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate(
       .SetMethod("takeHeapSnapshot", &WebContents::TakeHeapSnapshot)
       .SetMethod("setImageAnimationPolicy",
                  &WebContents::SetImageAnimationPolicy)
+      .SetMethod("_getProcessMemoryInfo", &WebContents::GetProcessMemoryInfo)
       .SetProperty("id", &WebContents::ID)
       .SetProperty("session", &WebContents::Session)
       .SetProperty("hostWebContents", &WebContents::HostWebContents)

+ 1 - 0
shell/browser/api/electron_api_web_contents.h

@@ -324,6 +324,7 @@ class WebContents : public gin::Wrappable<WebContents>,
 
   v8::Local<v8::Promise> TakeHeapSnapshot(v8::Isolate* isolate,
                                           const base::FilePath& file_path);
+  v8::Local<v8::Promise> GetProcessMemoryInfo(v8::Isolate* isolate);
 
   // Properties.
   int32_t ID() const { return id_; }

+ 9 - 4
shell/common/api/electron_bindings.cc

@@ -50,7 +50,9 @@ void ElectronBindings::BindProcess(v8::Isolate* isolate,
   process->SetMethod("getCreationTime", &GetCreationTime);
   process->SetMethod("getHeapStatistics", &GetHeapStatistics);
   process->SetMethod("getBlinkMemoryInfo", &GetBlinkMemoryInfo);
-  process->SetMethod("getProcessMemoryInfo", &GetProcessMemoryInfo);
+  if (gin_helper::Locker::IsBrowserProcess()) {
+    process->SetMethod("getProcessMemoryInfo", &GetProcessMemoryInfo);
+  }
   process->SetMethod("getSystemMemoryInfo", &GetSystemMemoryInfo);
   process->SetMethod("getSystemVersion",
                      &base::SysInfo::OperatingSystemVersion);
@@ -207,10 +209,11 @@ v8::Local<v8::Value> ElectronBindings::GetSystemMemoryInfo(
 // static
 v8::Local<v8::Promise> ElectronBindings::GetProcessMemoryInfo(
     v8::Isolate* isolate) {
+  CHECK(gin_helper::Locker::IsBrowserProcess());
   gin_helper::Promise<gin_helper::Dictionary> promise(isolate);
   v8::Local<v8::Promise> handle = promise.GetHandle();
 
-  if (gin_helper::Locker::IsBrowserProcess() && !Browser::Get()->is_ready()) {
+  if (!Browser::Get()->is_ready()) {
     promise.RejectWithErrorMessage(
         "Memory Info is available only after app ready");
     return handle;
@@ -221,7 +224,8 @@ v8::Local<v8::Promise> ElectronBindings::GetProcessMemoryInfo(
       ->RequestGlobalDumpForPid(
           base::GetCurrentProcId(), std::vector<std::string>(),
           base::BindOnce(&ElectronBindings::DidReceiveMemoryDump,
-                         std::move(context), std::move(promise)));
+                         std::move(context), std::move(promise),
+                         base::GetCurrentProcId()));
   return handle;
 }
 
@@ -242,6 +246,7 @@ v8::Local<v8::Value> ElectronBindings::GetBlinkMemoryInfo(
 void ElectronBindings::DidReceiveMemoryDump(
     v8::Global<v8::Context> context,
     gin_helper::Promise<gin_helper::Dictionary> promise,
+    base::ProcessId target_pid,
     bool success,
     std::unique_ptr<memory_instrumentation::GlobalMemoryDump> global_dump) {
   v8::Isolate* isolate = promise.isolate();
@@ -259,7 +264,7 @@ void ElectronBindings::DidReceiveMemoryDump(
   bool resolved = false;
   for (const memory_instrumentation::GlobalMemoryDump::ProcessDump& dump :
        global_dump->process_dumps()) {
-    if (base::GetCurrentProcId() == dump.pid()) {
+    if (target_pid == dump.pid()) {
       gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
       const auto& osdump = dump.os_dump();
 #if defined(OS_LINUX) || defined(OS_WIN)

+ 7 - 6
shell/common/api/electron_bindings.h

@@ -49,6 +49,13 @@ class ElectronBindings {
 
   static void Crash();
 
+  static void DidReceiveMemoryDump(
+      v8::Global<v8::Context> context,
+      gin_helper::Promise<gin_helper::Dictionary> promise,
+      base::ProcessId target_pid,
+      bool success,
+      std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump);
+
  private:
   static void Hang();
   static v8::Local<v8::Value> GetHeapStatistics(v8::Isolate* isolate);
@@ -67,12 +74,6 @@ class ElectronBindings {
 
   static void OnCallNextTick(uv_async_t* handle);
 
-  static void DidReceiveMemoryDump(
-      v8::Global<v8::Context> context,
-      gin_helper::Promise<gin_helper::Dictionary> promise,
-      bool success,
-      std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump);
-
   UvHandle<uv_async_t> call_next_tick_async_;
   std::list<node::Environment*> pending_next_ticks_;
   std::unique_ptr<base::ProcessMetrics> metrics_;

+ 1 - 0
typings/internal-electron.d.ts

@@ -58,6 +58,7 @@ declare namespace Electron {
     _loadURL(url: string, options: ElectronInternal.LoadURLOptions): void;
     getOwnerBrowserWindow(): Electron.BrowserWindow;
     getLastWebPreferences(): Electron.WebPreferences;
+    _getProcessMemoryInfo(): Electron.ProcessMemoryInfo;
     _getPreloadPaths(): string[];
     equal(other: WebContents): boolean;
     browserWindowOptions: BrowserWindowConstructorOptions;