Add two new profiling modes for OOP HP.

kAllRenderers will profile all renderers. This allows a user to easily debug
renderer-based memory issues. Adding this mode also allows the removal of some
testing code that had the same effect.

kManual allows the user to manually specify the processes to profile via
chrome://memory-internals. If the user starts profiling a process while in
another mode, the mode will change to kManual for simplicity.

This CL renames the function ShouldProfileProcessType to
ShouldProfileNonRendererProcessType. This CL fixes a bug in
BackgroundProfilingTrigger whereby renderers would never be profiled, since
ShouldProfileProcessType() was incorrectly being used. This logic is no longer
necessary since BackgroundProfilingTrigger queries for all profiled processes by
pid.

Bug: 
Change-Id: Ibeca2346f1629292ca17678081cf0aec68a85ab3
Reviewed-on: https://chromium-review.googlesource.com/818181
Commit-Queue: Erik Chen <[email protected]>
Reviewed-by: Albert J. Wong <[email protected]>
Reviewed-by: Brett Wilson <[email protected]>
Cr-Commit-Position: refs/heads/master@{#523275}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 9ef2052..cfff9f7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1059,7 +1059,12 @@
     {flag_descriptions::kEnableOutOfProcessHeapProfilingModeGpu,
      switches::kMemlog, switches::kMemlogModeGpu},
     {flag_descriptions::kEnableOutOfProcessHeapProfilingModeRendererSampling,
-     switches::kMemlog, switches::kMemlogModeRendererSampling}};
+     switches::kMemlog, switches::kMemlogModeRendererSampling},
+    {flag_descriptions::kEnableOutOfProcessHeapProfilingModeAllRenderers,
+     switches::kMemlog, switches::kMemlogModeAllRenderers},
+    {flag_descriptions::kEnableOutOfProcessHeapProfilingModeManual,
+     switches::kMemlog, switches::kMemlogModeManual},
+};
 
 const FeatureEntry::FeatureParam kOmniboxUIMaxAutocompleteMatches4[] = {
     {OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam, "4"}};
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 250ede5d..bdc2853 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -499,10 +499,15 @@
 const char kEnableOutOfProcessHeapProfilingModeMinimal[] =
     "Profile only the browser and GPU processes.";
 const char kEnableOutOfProcessHeapProfilingModeAll[] = "Profile all processes.";
+const char kEnableOutOfProcessHeapProfilingModeAllRenderers[] =
+    "Profiles all renderers.";
 const char kEnableOutOfProcessHeapProfilingModeBrowser[] =
     "Profile only the browser processes.";
 const char kEnableOutOfProcessHeapProfilingModeGpu[] =
     "Profile only the GPU processes.";
+const char kEnableOutOfProcessHeapProfilingModeManual[] =
+    "By default, no processes are profiled. User may choose to start-profiling "
+    "processes via chrome://memory-internals.";
 const char kEnableOutOfProcessHeapProfilingModeRendererSampling[] =
     "Profile a random sampling of renderer processes, ensuring only one is "
     "ever profiled at a time.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 8f8cb914..a6f3e462c 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -320,8 +320,10 @@
 extern const char kEnableOutOfProcessHeapProfilingDescription[];
 extern const char kEnableOutOfProcessHeapProfilingModeMinimal[];
 extern const char kEnableOutOfProcessHeapProfilingModeAll[];
+extern const char kEnableOutOfProcessHeapProfilingModeAllRenderers[];
 extern const char kEnableOutOfProcessHeapProfilingModeBrowser[];
 extern const char kEnableOutOfProcessHeapProfilingModeGpu[];
+extern const char kEnableOutOfProcessHeapProfilingModeManual[];
 extern const char kEnableOutOfProcessHeapProfilingModeRendererSampling[];
 extern const char kOutOfProcessHeapProfilingKeepSmallAllocations[];
 extern const char kOutOfProcessHeapProfilingKeepSmallAllocationsDescription[];
diff --git a/chrome/browser/profiling_host/background_profiling_triggers.cc b/chrome/browser/profiling_host/background_profiling_triggers.cc
index 54406359..b11d60e0 100644
--- a/chrome/browser/profiling_host/background_profiling_triggers.cc
+++ b/chrome/browser/profiling_host/background_profiling_triggers.cc
@@ -101,10 +101,6 @@
 bool BackgroundProfilingTriggers::IsOverTriggerThreshold(
     int content_process_type,
     uint32_t private_footprint_kb) {
-  if (!host_->ShouldProfileProcessType(content_process_type)) {
-    return false;
-  }
-
   switch (content_process_type) {
     case content::ProcessType::PROCESS_TYPE_BROWSER:
       return private_footprint_kb > kBrowserProcessMallocTriggerKb;
diff --git a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
index 128a3561..da8c9fc 100644
--- a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
+++ b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
@@ -98,8 +98,6 @@
         nullptr);
   }
 
-  void SetMode(ProfilingProcessHost::Mode mode) { host_.SetMode(mode); }
-
  protected:
   base::test::ScopedTaskEnvironment scoped_task_envrionment_;
   content::TestBrowserThreadBundle thread_bundle;
@@ -116,8 +114,6 @@
 //  * robust to empty memory dumps.
 //  * does not trigger if below a size threshold.
 TEST_F(BackgroundProfilingTriggersTest, OnReceivedMemoryDump_EmptyCases) {
-  SetMode(ProfilingProcessHost::Mode::kAll);
-
   GlobalMemoryDumpPtr dump_empty(
       memory_instrumentation::mojom::GlobalMemoryDump::New());
   triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump_empty));
@@ -154,32 +150,7 @@
   triggers_.Reset();
 }
 
-// kNone mode shold trigger nothing.
-TEST_F(BackgroundProfilingTriggersTest, OnReceivedMemoryDump_ModeNone) {
-  SetMode(ProfilingProcessHost::Mode::kNone);
-
-  GlobalMemoryDumpPtr dump(
-      memory_instrumentation::mojom::GlobalMemoryDump::New());
-  PopulateMetrics(&dump, 1, ProcessType::BROWSER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 2, ProcessType::RENDERER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 3, ProcessType::RENDERER, 1, 1, 1);
-  PopulateMetrics(&dump, 4, ProcessType::GPU, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 5, ProcessType::OTHER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 6, ProcessType::RENDERER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_FALSE(triggers_.WasReportTriggered());
-}
-
-// kAll mode only reports everything over the large threshold.
-TEST_F(BackgroundProfilingTriggersTest, OnReceivedMemoryDump_ModeAll) {
-  SetMode(ProfilingProcessHost::Mode::kAll);
-
+TEST_F(BackgroundProfilingTriggersTest, OnReceivedMemoryDump_ProfiledPids) {
   GlobalMemoryDumpPtr dump(
       memory_instrumentation::mojom::GlobalMemoryDump::New());
   PopulateMetrics(&dump, 1, ProcessType::RENDERER, 1, 1, 1);
@@ -215,8 +186,6 @@
 
 // Non-profiled processes don't trigger.
 TEST_F(BackgroundProfilingTriggersTest, OnlyProfiledProcessesTrigger) {
-  SetMode(ProfilingProcessHost::Mode::kAll);
-
   GlobalMemoryDumpPtr dump(
       memory_instrumentation::mojom::GlobalMemoryDump::New());
   PopulateMetrics(&dump, 101, ProcessType::BROWSER, kProcessMallocTriggerKb,
@@ -231,127 +200,6 @@
   EXPECT_TRUE(triggers_.WasReportTriggered());
 }
 
-// kMinimal mode only reports browser and gpu processes.
-TEST_F(BackgroundProfilingTriggersTest, OnReceivedMemoryDump_ModeMinimal) {
-  SetMode(ProfilingProcessHost::Mode::kMinimal);
-
-  GlobalMemoryDumpPtr dump(
-      memory_instrumentation::mojom::GlobalMemoryDump::New());
-  PopulateMetrics(&dump, 1, ProcessType::BROWSER, 1, 1, 1);
-  PopulateMetrics(&dump, 2, ProcessType::GPU, 1, 1, 1);
-  PopulateMetrics(&dump, 3, ProcessType::OTHER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 4, ProcessType::RENDERER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-
-  // Ensure Browser and GPU processes under threshold do not trigger.
-  // Ensure other process types ignored.
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_FALSE(triggers_.WasReportTriggered());
-
-  // Ensure BROWSER and GPU types trigger.
-  triggers_.Reset();
-  dump = memory_instrumentation::mojom::GlobalMemoryDump::New();
-  PopulateMetrics(&dump, 1, ProcessType::BROWSER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 2, ProcessType::GPU, 1, 1, 1);
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_TRUE(triggers_.WasReportTriggered());
-
-  triggers_.Reset();
-  dump = memory_instrumentation::mojom::GlobalMemoryDump::New();
-  PopulateMetrics(&dump, 1, ProcessType::GPU, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 2, ProcessType::BROWSER, 1, 1, 1);
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_TRUE(triggers_.WasReportTriggered());
-}
-
-// kBrowser mode only reports browser.
-TEST_F(BackgroundProfilingTriggersTest, OnReceivedMemoryDump_ModeBrowser) {
-  SetMode(ProfilingProcessHost::Mode::kBrowser);
-
-  GlobalMemoryDumpPtr dump(
-      memory_instrumentation::mojom::GlobalMemoryDump::New());
-  PopulateMetrics(&dump, 1, ProcessType::BROWSER, 1, 1, 1);
-  PopulateMetrics(&dump, 2, ProcessType::GPU, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 3, ProcessType::OTHER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 4, ProcessType::RENDERER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-
-  // Ensure Browser processes under threshold do not trigger.
-  // Ensure other process types ignored.
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_FALSE(triggers_.WasReportTriggered());
-
-  // Ensure BROWSER type triggers.
-  triggers_.Reset();
-  dump = memory_instrumentation::mojom::GlobalMemoryDump::New();
-  PopulateMetrics(&dump, 1, ProcessType::BROWSER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_TRUE(triggers_.WasReportTriggered());
-}
-
-// kGpu mode only reports gpu.
-TEST_F(BackgroundProfilingTriggersTest, OnReceivedMemoryDump_ModeGpu) {
-  SetMode(ProfilingProcessHost::Mode::kGpu);
-
-  GlobalMemoryDumpPtr dump(
-      memory_instrumentation::mojom::GlobalMemoryDump::New());
-  PopulateMetrics(&dump, 1, ProcessType::GPU, 1, 1, 1);
-  PopulateMetrics(&dump, 2, ProcessType::BROWSER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 3, ProcessType::OTHER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 4, ProcessType::RENDERER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-
-  // Ensure GPU processes under threshold do not trigger.
-  // Ensure other process types ignored.
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_FALSE(triggers_.WasReportTriggered());
-
-  // Ensure GPU type triggers.
-  triggers_.Reset();
-  dump = memory_instrumentation::mojom::GlobalMemoryDump::New();
-  PopulateMetrics(&dump, 1, ProcessType::GPU, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_TRUE(triggers_.WasReportTriggered());
-}
-
-// kRendererSampling mode only the single profiled renderer.
-TEST_F(BackgroundProfilingTriggersTest,
-       DISABLED_OnReceivedMemoryDump_ModeRendererSampling) {
-  SetMode(ProfilingProcessHost::Mode::kRendererSampling);
-
-  GlobalMemoryDumpPtr dump(
-      memory_instrumentation::mojom::GlobalMemoryDump::New());
-  PopulateMetrics(&dump, 1, ProcessType::RENDERER, 1, 1, 1);
-  PopulateMetrics(&dump, 2, ProcessType::BROWSER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 3, ProcessType::GPU, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  PopulateMetrics(&dump, 4, ProcessType::OTHER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-
-  // Ensure RENDERER processes under threshold do not trigger.
-  // Ensure other process types ignored.
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_FALSE(triggers_.WasReportTriggered());
-
-  // Ensure RENDERER type triggers.
-  triggers_.Reset();
-  dump = memory_instrumentation::mojom::GlobalMemoryDump::New();
-  PopulateMetrics(&dump, 1, ProcessType::RENDERER, kProcessMallocTriggerKb,
-                  kProcessMallocTriggerKb, kProcessMallocTriggerKb);
-  triggers_.OnReceivedMemoryDump(profiled_pids_, true, std::move(dump));
-  EXPECT_TRUE(triggers_.WasReportTriggered());
-}
-
 // Ensure IsAllowedToUpload() respects metrics collection settings.
 TEST_F(BackgroundProfilingTriggersTest, IsAllowedToUpload_Metrics) {
   EXPECT_TRUE(triggers_.IsAllowedToUpload());
diff --git a/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc b/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc
index 41e040c..d997935 100644
--- a/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc
+++ b/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc
@@ -23,7 +23,7 @@
   (void)connection;  // Unused variable.
 #else
   profiling::ProfilingProcessHost::Mode mode =
-      profiling::ProfilingProcessHost::GetCurrentMode();
+      profiling::ProfilingProcessHost::GetModeForStartup();
   if (mode != profiling::ProfilingProcessHost::Mode::kNone)
     profiling::ProfilingProcessHost::Start(connection, mode);
 #endif
diff --git a/chrome/browser/profiling_host/memlog_browsertest.cc b/chrome/browser/profiling_host/memlog_browsertest.cc
index 6dbe9f9..bc4807ed 100644
--- a/chrome/browser/profiling_host/memlog_browsertest.cc
+++ b/chrome/browser/profiling_host/memlog_browsertest.cc
@@ -173,13 +173,6 @@
   }
 
   void SetUp() override {
-    // Force the renderer to be sampled in RendererSampling mode for
-    // deterministic tests.
-    if (GetParam() == switches::kMemlogModeRendererSampling) {
-      profiling::ProfilingProcessHost::GetInstance()
-          ->SetRendererSamplingAlwaysProfileForTest();
-    }
-
     partition_allocator_.init();
     InProcessBrowserTest::SetUp();
   }
@@ -251,7 +244,7 @@
                                                        ->GetHandle());
     base::Value* heaps_v2 = FindHeapsV2(renderer_pid, dump_json);
     if (GetParam() == switches::kMemlogModeAll ||
-        GetParam() == switches::kMemlogModeRendererSampling) {
+        GetParam() == switches::kMemlogModeAllRenderers) {
       ASSERT_TRUE(heaps_v2);
 
       // ValidateDump doesn't always succeed for the renderer, since we don't do
@@ -264,9 +257,8 @@
           << "There should be no heap dump for the renderer.";
     }
 
-    // RendererSampling guarantees only 1 renderer is ever sampled at a time.
-    if (GetParam() == switches::kMemlogModeRendererSampling) {
-      EXPECT_EQ(1, NumProcessesWithName(dump_json, "Renderer"));
+    if (GetParam() == switches::kMemlogModeAllRenderers) {
+      EXPECT_GE(1, NumProcessesWithName(dump_json, "Renderer"));
     } else {
       EXPECT_GT(NumProcessesWithName(dump_json, "Renderer"), 0);
     }
@@ -391,7 +383,7 @@
         ReadDumpFile(renderer_dumpfile_path);
 
     if (GetParam() == switches::kMemlogModeAll ||
-        GetParam() == switches::kMemlogModeRendererSampling) {
+        GetParam() == switches::kMemlogModeAllRenderers) {
       ASSERT_TRUE(dump_json);
       ValidateRendererAllocations(dump_json.get());
     }
@@ -433,10 +425,9 @@
 INSTANTIATE_TEST_CASE_P(GpuOnly,
                         MemlogBrowserTest,
                         ::testing::Values(switches::kMemlogModeGpu));
-INSTANTIATE_TEST_CASE_P(
-    RendererSampling,
-    MemlogBrowserTest,
-    ::testing::Values(switches::kMemlogModeRendererSampling));
+INSTANTIATE_TEST_CASE_P(AllRenderers,
+                        MemlogBrowserTest,
+                        ::testing::Values(switches::kMemlogModeAllRenderers));
 
 }  // namespace profiling
 
diff --git a/chrome/browser/profiling_host/profiling_process_host.cc b/chrome/browser/profiling_host/profiling_process_host.cc
index 50980bd2..a50f462 100644
--- a/chrome/browser/profiling_host/profiling_process_host.cc
+++ b/chrome/browser/profiling_host/profiling_process_host.cc
@@ -190,10 +190,7 @@
 }  // namespace
 
 ProfilingProcessHost::ProfilingProcessHost()
-    : is_registered_(false),
-      background_triggers_(this),
-      mode_(Mode::kNone),
-      always_sample_for_tests_(false) {}
+    : is_registered_(false), background_triggers_(this), mode_(Mode::kNone) {}
 
 ProfilingProcessHost::~ProfilingProcessHost() {
   if (is_registered_)
@@ -225,7 +222,7 @@
   // so as not to collide with logic in ProfilingProcessHost::Observe().
   DCHECK_NE(data.process_type, content::ProcessType::PROCESS_TYPE_RENDERER);
 
-  if (!ShouldProfileProcessType(data.process_type)) {
+  if (!ShouldProfileNonRendererProcessType(data.process_type)) {
     return;
   }
 
@@ -358,7 +355,7 @@
 }
 
 // static
-ProfilingProcessHost::Mode ProfilingProcessHost::GetCurrentMode() {
+ProfilingProcessHost::Mode ProfilingProcessHost::GetModeForStartup() {
   const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
   if (cmdline->HasSwitch(switches::kMemlog) ||
@@ -398,6 +395,10 @@
     const std::string& mode) {
   if (mode == switches::kMemlogModeAll)
     return Mode::kAll;
+  if (mode == switches::kMemlogModeAllRenderers)
+    return Mode::kAllRenderers;
+  if (mode == switches::kMemlogModeManual)
+    return Mode::kManual;
   if (mode == switches::kMemlogModeMinimal)
     return Mode::kMinimal;
   if (mode == switches::kMemlogModeBrowser)
@@ -603,9 +604,16 @@
   profiling_service_->GetProfiledPids(std::move(post_result_to_ui_thread));
 }
 
-void ProfilingProcessHost::StartProfiling(base::ProcessId pid) {
+void ProfilingProcessHost::StartManualProfiling(base::ProcessId pid) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
+  if (!has_started_) {
+    profiling::ProfilingProcessHost::Start(
+        content::ServiceManagerConnection::GetForProcess(), Mode::kManual);
+  } else {
+    SetMode(Mode::kManual);
+  }
+
   // The RenderProcessHost iterator must be used on the UI thread.
   // The BrowserChildProcessHostIterator iterator must be used on the IO thread.
   for (auto iter = content::RenderProcessHost::AllHostsIterator();
@@ -679,7 +687,8 @@
   connector_->BindInterface(mojom::kServiceName, &profiling_service_);
 
   // Start profiling the browser if the mode allows.
-  if (ShouldProfileProcessType(content::ProcessType::PROCESS_TYPE_BROWSER)) {
+  if (ShouldProfileNonRendererProcessType(
+          content::ProcessType::PROCESS_TYPE_BROWSER)) {
     ProfilingClientBinder client(connector_.get());
     AddClientToProfilingService(client.take(), base::Process::Current().Pid(),
                                 profiling::mojom::ProcessType::BROWSER);
@@ -718,19 +727,28 @@
 }
 
 void ProfilingProcessHost::SetMode(Mode mode) {
+  base::AutoLock l(mode_lock_);
   mode_ = mode;
 }
 
 void ProfilingProcessHost::ReportMetrics() {
-  UMA_HISTOGRAM_ENUMERATION("OutOfProcessHeapProfiling.ProfilingMode", mode(),
-                            Mode::kCount);
+  UMA_HISTOGRAM_ENUMERATION("OutOfProcessHeapProfiling.ProfilingMode",
+                            GetMode(), Mode::kCount);
 }
 
-bool ProfilingProcessHost::ShouldProfileProcessType(int process_type) {
-  switch (mode()) {
+bool ProfilingProcessHost::ShouldProfileNonRendererProcessType(
+    int process_type) {
+  switch (GetMode()) {
     case Mode::kAll:
       return true;
 
+    case Mode::kAllRenderers:
+      // Renderer logic is handled in ProfilingProcessHost::Observe.
+      return false;
+
+    case Mode::kManual:
+      return false;
+
     case Mode::kMinimal:
       return (process_type == content::ProcessType::PROCESS_TYPE_GPU ||
               process_type == content::ProcessType::PROCESS_TYPE_BROWSER);
@@ -742,10 +760,7 @@
       return process_type == content::ProcessType::PROCESS_TYPE_BROWSER;
 
     case Mode::kRendererSampling:
-      // This seems odd because a renderer does get profiled. However, since
-      // the general rule for the whole type is to not profile in this mode,
-      // returning false is appropriate. kRendererSampling has special case
-      // logic elsewhere to enable rendering specifically chosed renderers.
+      // Renderer logic is handled in ProfilingProcessHost::Observe.
       return false;
 
     case Mode::kNone:
@@ -761,20 +776,17 @@
 }
 
 bool ProfilingProcessHost::ShouldProfileNewRenderer(
-    content::RenderProcessHost* renderer) const {
+    content::RenderProcessHost* renderer) {
+  Mode mode = GetMode();
   // Never profile incognito processes.
   if (Profile::FromBrowserContext(renderer->GetBrowserContext())
           ->GetProfileType() == Profile::INCOGNITO_PROFILE) {
     return false;
   }
 
-  if (mode() == Mode::kAll) {
+  if (mode == Mode::kAll || mode == Mode::kAllRenderers) {
     return true;
-  } else if (mode() == Mode::kRendererSampling && profiled_renderers_.empty()) {
-    if (always_sample_for_tests_) {
-      return true;
-    }
-
+  } else if (mode == Mode::kRendererSampling && profiled_renderers_.empty()) {
     // Sample renderers with a 1/3 probability.
     return (base::RandUint64() % 100000) < 33333;
   }
@@ -831,10 +843,6 @@
                          profiling::mojom::ProcessType::RENDERER));
 }
 
-void ProfilingProcessHost::SetRendererSamplingAlwaysProfileForTest() {
-  always_sample_for_tests_ = true;
-}
-
 bool ProfilingProcessHost::TakingTraceForUpload() {
   base::AutoLock lock(taking_trace_for_upload_lock_);
   return taking_trace_for_upload_;
diff --git a/chrome/browser/profiling_host/profiling_process_host.h b/chrome/browser/profiling_host/profiling_process_host.h
index 4f902833..5d792df 100644
--- a/chrome/browser/profiling_host/profiling_process_host.h
+++ b/chrome/browser/profiling_host/profiling_process_host.h
@@ -81,16 +81,26 @@
     // Profile a sampled number of renderer processes.
     kRendererSampling = 5,
 
+    // Profile all renderer processes.
+    kAllRenderers = 6,
+
+    // By default, profile no processes. User may choose to start profiling for
+    // processes via chrome://memory-internals.
+    kManual = 7,
+
     kCount
   };
 
   // Returns the mode.
-  Mode mode() const { return mode_; }
+  Mode GetMode() {
+    base::AutoLock l(mode_lock_);
+    return mode_;
+  }
 
-  // Returns the mode set on the current process' command line.
-  static Mode GetCurrentMode();
+  // Returns the mode specified by the command line or via about://flags.
+  static Mode GetModeForStartup();
   static Mode ConvertStringToMode(const std::string& input);
-  bool ShouldProfileProcessType(int process_type);
+  bool ShouldProfileNonRendererProcessType(int process_type);
 
   // Launches the profiling process and returns a pointer to it.
   static ProfilingProcessHost* Start(
@@ -144,7 +154,7 @@
   void GetProfiledPids(GetProfiledPidsCallback callback);
 
   // Starts profiling the process with the given id.
-  void StartProfiling(base::ProcessId pid);
+  void StartManualProfiling(base::ProcessId pid);
 
  private:
   friend struct base::DefaultSingletonTraits<ProfilingProcessHost>;
@@ -159,7 +169,7 @@
   void Register();
   void Unregister();
 
-  // Set the profiling mode. Exposed for unittests.
+  // Set/Get the profiling mode. Exposed for unittests.
   void SetMode(Mode mode);
 
   // Make and store a connector from |connection|.
@@ -208,7 +218,7 @@
   void ReportMetrics();
 
   // Helpers for controlling process selection for the sampling modes.
-  bool ShouldProfileNewRenderer(content::RenderProcessHost* renderer) const;
+  bool ShouldProfileNewRenderer(content::RenderProcessHost* renderer);
 
   // Sets up the profiling connection for the given child process.
   void StartProfilingNonRendererChild(const content::ChildProcessData&);
@@ -219,9 +229,6 @@
 
   void StartProfilingRenderer(content::RenderProcessHost* host);
 
-  // SetRenderer.
-  void SetRendererSamplingAlwaysProfileForTest();
-
   void GetProfiledPidsOnIOThread(GetProfiledPidsCallback callback);
   void StartProfilingPidOnIOThread(base::ProcessId pid);
 
@@ -244,6 +251,7 @@
 
   // The mode determines which processes should be profiled.
   Mode mode_;
+  base::Lock mode_lock_;
 
   // Whether or not the profiling host is started.
   static bool has_started_;
@@ -264,10 +272,6 @@
   // simplicity, it's easier to just track this variable in this process.
   std::unordered_set<void*> profiled_renderers_;
 
-  // For Tests. In kRendererSampling mode, overrides sampling to always profile
-  // a renderer process if one is already not going.
-  bool always_sample_for_tests_;
-
   // Must only ever be used from the UI thread. Will be called after the
   // profiling process dumps heaps into the trace log and MDPs have been given
   // time to do the same.
diff --git a/chrome/browser/profiling_host/profiling_process_host_unittest.cc b/chrome/browser/profiling_host/profiling_process_host_unittest.cc
index ae5ac7b..a568349 100644
--- a/chrome/browser/profiling_host/profiling_process_host_unittest.cc
+++ b/chrome/browser/profiling_host/profiling_process_host_unittest.cc
@@ -36,18 +36,18 @@
 
 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
 
-TEST(ProfilingProcessHost, GetCurrentMode_Default) {
+TEST(ProfilingProcessHost, GetModeForStartup_Default) {
   EXPECT_EQ(ProfilingProcessHost::Mode::kNone,
-            ProfilingProcessHost::GetCurrentMode());
+            ProfilingProcessHost::GetModeForStartup());
 }
 
-TEST(ProfilingProcessHost, GetCurrentMode_Commandline) {
+TEST(ProfilingProcessHost, GetModeForStartup_Commandline) {
   {
     base::test::ScopedCommandLine scoped_command_line;
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kMemlog,
                                                               "");
     EXPECT_EQ(ProfilingProcessHost::Mode::kNone,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -55,7 +55,7 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kMemlog,
                                                               "invalid");
     EXPECT_EQ(ProfilingProcessHost::Mode::kNone,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -63,7 +63,7 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kMemlog, switches::kMemlogModeAll);
     EXPECT_EQ(ProfilingProcessHost::Mode::kAll,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -71,7 +71,7 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kMemlog, switches::kMemlogModeBrowser);
     EXPECT_EQ(ProfilingProcessHost::Mode::kBrowser,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -79,7 +79,7 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kMemlog, switches::kMemlogModeMinimal);
     EXPECT_EQ(ProfilingProcessHost::Mode::kMinimal,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -87,7 +87,7 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kMemlog, switches::kMemlogModeGpu);
     EXPECT_EQ(ProfilingProcessHost::Mode::kGpu,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -95,13 +95,13 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kMemlog, switches::kMemlogModeRendererSampling);
     EXPECT_EQ(ProfilingProcessHost::Mode::kRendererSampling,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 }
 
-TEST(ProfilingProcessHost, GetCurrentMode_Finch) {
+TEST(ProfilingProcessHost, GetModeForStartup_Finch) {
   EXPECT_EQ(ProfilingProcessHost::Mode::kNone,
-            ProfilingProcessHost::GetCurrentMode());
+            ProfilingProcessHost::GetModeForStartup());
   std::map<std::string, std::string> parameters;
 
   {
@@ -111,7 +111,7 @@
         profiling::kOOPHeapProfilingFeature, parameters);
 
     EXPECT_EQ(ProfilingProcessHost::Mode::kNone,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -120,7 +120,7 @@
     scoped_feature_list.InitAndEnableFeatureWithParameters(
         profiling::kOOPHeapProfilingFeature, parameters);
     EXPECT_EQ(ProfilingProcessHost::Mode::kNone,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -130,7 +130,7 @@
     scoped_feature_list.InitAndEnableFeatureWithParameters(
         profiling::kOOPHeapProfilingFeature, parameters);
     EXPECT_EQ(ProfilingProcessHost::Mode::kAll,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -140,7 +140,7 @@
     scoped_feature_list.InitAndEnableFeatureWithParameters(
         profiling::kOOPHeapProfilingFeature, parameters);
     EXPECT_EQ(ProfilingProcessHost::Mode::kBrowser,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -150,7 +150,7 @@
     scoped_feature_list.InitAndEnableFeatureWithParameters(
         profiling::kOOPHeapProfilingFeature, parameters);
     EXPECT_EQ(ProfilingProcessHost::Mode::kMinimal,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -160,7 +160,7 @@
     scoped_feature_list.InitAndEnableFeatureWithParameters(
         profiling::kOOPHeapProfilingFeature, parameters);
     EXPECT_EQ(ProfilingProcessHost::Mode::kGpu,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -170,12 +170,12 @@
     scoped_feature_list.InitAndEnableFeatureWithParameters(
         profiling::kOOPHeapProfilingFeature, parameters);
     EXPECT_EQ(ProfilingProcessHost::Mode::kRendererSampling,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 }
 
 // Ensure the commandline overrides any given field trial.
-TEST(ProfilingProcessHost, GetCurrentMode_CommandLinePrecedence) {
+TEST(ProfilingProcessHost, GetModeForStartup_CommandLinePrecedence) {
   base::test::ScopedCommandLine scoped_command_line;
   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
       switches::kMemlog, switches::kMemlogModeAll);
@@ -188,18 +188,18 @@
       profiling::kOOPHeapProfilingFeature, parameters);
 
   EXPECT_EQ(ProfilingProcessHost::Mode::kAll,
-            ProfilingProcessHost::GetCurrentMode());
+            ProfilingProcessHost::GetModeForStartup());
 }
 
 #else
 
-TEST(ProfilingProcessHost, GetCurrentMode_NoModeWithoutShim) {
+TEST(ProfilingProcessHost, GetModeForStartup_NoModeWithoutShim) {
   {
     base::test::ScopedCommandLine scoped_command_line;
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kMemlog, switches::kMemlogModeAll);
     EXPECT_EQ(ProfilingProcessHost::Mode::kNone,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 
   {
@@ -210,7 +210,7 @@
     scoped_feature_list.InitAndEnableFeatureWithParameters(
         profiling::kOOPHeapProfilingFeature, parameters);
     EXPECT_EQ(ProfilingProcessHost::Mode::kNone,
-              ProfilingProcessHost::GetCurrentMode());
+              ProfilingProcessHost::GetModeForStartup());
   }
 }
 
diff --git a/chrome/browser/profiling_host/profiling_test_driver.cc b/chrome/browser/profiling_host/profiling_test_driver.cc
index b444ec2..452eeb52 100644
--- a/chrome/browser/profiling_host/profiling_test_driver.cc
+++ b/chrome/browser/profiling_host/profiling_test_driver.cc
@@ -281,11 +281,6 @@
 bool ProfilingTestDriver::RunInitializationOnUIThread() {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
-  if (options_.mode == ProfilingProcessHost::Mode::kRendererSampling) {
-    profiling::ProfilingProcessHost::GetInstance()
-        ->SetRendererSamplingAlwaysProfileForTest();
-  }
-
   LOG(ERROR) << "RunInitializationOnUIThread: "
              << base::CommandLine::ForCurrentProcess()->GetCommandLineString();
   if (!CheckOrStartProfiling())
@@ -439,7 +434,7 @@
   base::ProcessId renderer_pid = static_cast<base::ProcessId>(pid);
   base::Value* heaps_v2 = FindHeapsV2(renderer_pid, dump_json);
   if (options_.mode == ProfilingProcessHost::Mode::kAll ||
-      options_.mode == ProfilingProcessHost::Mode::kRendererSampling) {
+      options_.mode == ProfilingProcessHost::Mode::kAllRenderers) {
     if (!heaps_v2) {
       LOG(ERROR) << "Failed to find heaps v2 for renderer";
       return false;
@@ -457,10 +452,9 @@
     }
   }
 
-  // RendererSampling guarantees only 1 renderer is ever sampled at a time.
-  if (options_.mode == ProfilingProcessHost::Mode::kRendererSampling) {
-    if (NumProcessesWithName(dump_json, "Renderer", nullptr) != 1) {
-      LOG(ERROR) << "There should be exactly 1 renderer dump";
+  if (options_.mode == ProfilingProcessHost::Mode::kAllRenderers) {
+    if (NumProcessesWithName(dump_json, "Renderer", nullptr) == 0) {
+      LOG(ERROR) << "There should be at least 1 renderer dump";
       return false;
     }
   } else {
diff --git a/chrome/browser/ui/webui/memory_internals_ui.cc b/chrome/browser/ui/webui/memory_internals_ui.cc
index 0482d5c8..78e6518d 100644
--- a/chrome/browser/ui/webui/memory_internals_ui.cc
+++ b/chrome/browser/ui/webui/memory_internals_ui.cc
@@ -48,10 +48,13 @@
 // Returns the string to display at the top of the page for help.
 std::string GetMessageString() {
 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
-  switch (ProfilingProcessHost::GetCurrentMode()) {
+  switch (ProfilingProcessHost::GetInstance()->GetMode()) {
     case ProfilingProcessHost::Mode::kAll:
       return std::string("Memory logging is enabled for all processes.");
 
+    case ProfilingProcessHost::Mode::kAllRenderers:
+      return std::string("Memory logging is enabled for all renderers.");
+
     case ProfilingProcessHost::Mode::kBrowser:
       return std::string(
           "Memory logging is enabled for just the browser process.");
@@ -59,6 +62,11 @@
     case ProfilingProcessHost::Mode::kGpu:
       return std::string("Memory logging is enabled for just the gpu process.");
 
+    case ProfilingProcessHost::Mode::kManual:
+      return std::string(
+          "Memory logging must be manually enabled for each process via "
+          "chrome://memory-internals.");
+
     case ProfilingProcessHost::Mode::kMinimal:
       return std::string(
           "Memory logging is enabled for the browser and GPU processes.");
@@ -248,7 +256,7 @@
   if (!args->is_list() || args->GetList().size() != 1)
     return;
 
-  ProfilingProcessHost::GetInstance()->StartProfiling(
+  ProfilingProcessHost::GetInstance()->StartManualProfiling(
       args->GetList()[0].GetInt());
 }
 
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index a0f75f3..8d5dd20 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -473,8 +473,10 @@
 const char kMemlog[] = "memlog";
 const char kMemlogKeepSmallAllocations[] = "memlog-keep-small-allocations";
 const char kMemlogModeAll[] = "all";
+const char kMemlogModeAllRenderers[] = "all-renderers";
 const char kMemlogModeBrowser[] = "browser";
 const char kMemlogModeGpu[] = "gpu";
+const char kMemlogModeManual[] = "manual";
 const char kMemlogModeMinimal[] = "minimal";
 const char kMemlogModeRendererSampling[] = "renderer-sampling";
 
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 2ea79141..bcf7d1d2 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -150,8 +150,10 @@
 extern const char kMemlog[];
 extern const char kMemlogKeepSmallAllocations[];
 extern const char kMemlogModeAll[];
+extern const char kMemlogModeAllRenderers[];
 extern const char kMemlogModeBrowser[];
 extern const char kMemlogModeGpu[];
+extern const char kMemlogModeManual[];
 extern const char kMemlogModeMinimal[];
 extern const char kMemlogModeRendererSampling[];
 extern const char kMonitoringDestinationID[];
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 92c54f2..6b20d64 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -31861,6 +31861,8 @@
   <int value="3" label="Browser"/>
   <int value="4" label="Gpu"/>
   <int value="5" label="Renderer Sampling"/>
+  <int value="6" label="All renderers"/>
+  <int value="7" label="Manual"/>
 </enum>
 
 <enum name="OutOfProcessHeapProfilingProcessType">