[Chromecast] Application-specific command-line switches

Allow individual Cast web applications to set command-line switches
for the render process.

Bug: internal b/67735190
Bug: internal b/77323820
Test: cast_shell_browsertests, cast_shell_unittests
Change-Id: I2fdeca54e9f4a46f6299c58482e9934ebffe8b69
Reviewed-on: https://chromium-review.googlesource.com/1018205
Commit-Queue: James West <[email protected]>
Reviewed-by: Luke Halliwell <[email protected]>
Cr-Commit-Position: refs/heads/master@{#558077}
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 1d7c5fc6..72cf6cb0 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -73,6 +73,8 @@
     "network_context_manager.h",
     "pref_service_helper.cc",
     "pref_service_helper.h",
+    "renderer_config.cc",
+    "renderer_config.h",
     "renderer_prelauncher.cc",
     "renderer_prelauncher.h",
     "service/cast_service_simple.cc",
@@ -410,6 +412,7 @@
     "devtools/cast_devtools_manager_delegate_unittest.cc",
     "lru_renderer_cache_test.cc",
     "network_context_manager_unittest.cc",
+    "renderer_config_unittest.cc",
   ]
 
   deps = [
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 7b18381c..822a8f1 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -34,6 +34,7 @@
 #include "chromecast/browser/devtools/cast_devtools_manager_delegate.h"
 #include "chromecast/browser/grit/cast_browser_resources.h"
 #include "chromecast/browser/media/media_caps_impl.h"
+#include "chromecast/browser/renderer_config.h"
 #include "chromecast/browser/service/cast_service_simple.h"
 #include "chromecast/browser/url_request_context_factory.h"
 #include "chromecast/common/global_descriptors.h"
@@ -158,7 +159,8 @@
 
 CastContentBrowserClient::CastContentBrowserClient()
     : cast_browser_main_parts_(nullptr),
-      url_request_context_factory_(new URLRequestContextFactory()) {}
+      url_request_context_factory_(new URLRequestContextFactory()),
+      renderer_config_manager_(std::make_unique<RendererConfigManager>()) {}
 
 CastContentBrowserClient::~CastContentBrowserClient() {
   content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
@@ -457,6 +459,12 @@
     }
 #endif  // defined(USE_AURA)
   }
+
+  auto renderer_config =
+      renderer_config_manager_->GetRendererConfig(child_process_id);
+  if (renderer_config) {
+    renderer_config->AppendSwitchesTo(command_line);
+  }
 }
 
 void CastContentBrowserClient::OverrideWebkitPrefs(
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 2c186bb..278947ad 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -55,9 +55,9 @@
 }
 
 namespace shell {
-
 class CastBrowserMainParts;
 class CastResourceDispatcherHostDelegate;
+class RendererConfigManager;
 class URLRequestContextFactory;
 
 class CastContentBrowserClient : public content::ContentBrowserClient {
@@ -189,6 +189,10 @@
   std::unique_ptr<content::NavigationUIData> GetNavigationUIData(
       content::NavigationHandle* navigation_handle) override;
 
+  RendererConfigManager* renderer_config_manager() const {
+    return renderer_config_manager_.get();
+  }
+
  protected:
   CastContentBrowserClient();
 
@@ -234,6 +238,7 @@
   std::unique_ptr<CastResourceDispatcherHostDelegate>
       resource_dispatcher_host_delegate_;
   std::unique_ptr<media::CmaBackendFactory> cma_backend_factory_;
+  std::unique_ptr<RendererConfigManager> renderer_config_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(CastContentBrowserClient);
 };
diff --git a/chromecast/browser/lru_renderer_cache.cc b/chromecast/browser/lru_renderer_cache.cc
index 9a18bf8..552c8fd 100644
--- a/chromecast/browser/lru_renderer_cache.cc
+++ b/chromecast/browser/lru_renderer_cache.cc
@@ -8,18 +8,23 @@
 
 #include "base/bind.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "chromecast/browser/renderer_config.h"
 #include "chromecast/browser/renderer_prelauncher.h"
 #include "content/public/browser/site_instance.h"
 
 namespace chromecast {
 
-LRURendererCache::LRURendererCache(content::BrowserContext* browser_context,
-                                   size_t max_renderers)
+LRURendererCache::LRURendererCache(
+    content::BrowserContext* browser_context,
+    shell::RendererConfigManager* renderer_config_manager,
+    size_t max_renderers)
     : browser_context_(browser_context),
+      renderer_config_manager_(renderer_config_manager),
       max_renderers_(max_renderers),
       in_use_count_(0),
       weak_factory_(this) {
   DCHECK(browser_context_);
+  DCHECK(renderer_config_manager_);
   memory_pressure_listener_ =
       std::make_unique<base::MemoryPressureListener>(base::BindRepeating(
           &LRURendererCache::OnMemoryPressure, weak_factory_.GetWeakPtr()));
@@ -95,8 +100,9 @@
   if (factory_for_testing_) {
     cache_.push_front(factory_for_testing_->Create(browser_context_, page_url));
   } else {
-    cache_.push_front(
-        std::make_unique<RendererPrelauncher>(browser_context_, page_url));
+    cache_.push_front(std::make_unique<RendererPrelauncher>(
+        browser_context_,
+        renderer_config_manager_->CreateRendererConfigurator(), page_url));
   }
   // Evict the cache before prelaunching.
   EvictCache();
diff --git a/chromecast/browser/lru_renderer_cache.h b/chromecast/browser/lru_renderer_cache.h
index 0e94ed5..836d4c3 100644
--- a/chromecast/browser/lru_renderer_cache.h
+++ b/chromecast/browser/lru_renderer_cache.h
@@ -21,6 +21,10 @@
 namespace chromecast {
 class RendererPrelauncher;
 
+namespace shell {
+class RendererConfigManager;
+}  // namespace shell
+
 // Factory class for testing.
 class RendererPrelauncherFactory {
  public:
@@ -35,6 +39,7 @@
 class LRURendererCache {
  public:
   LRURendererCache(content::BrowserContext* browser_context,
+                   shell::RendererConfigManager* renderer_config_manager,
                    size_t max_renderers);
   virtual ~LRURendererCache();
 
@@ -64,6 +69,7 @@
   void EvictCache();
 
   content::BrowserContext* const browser_context_;
+  shell::RendererConfigManager* const renderer_config_manager_;
   const size_t max_renderers_;
   size_t in_use_count_;
   std::list<std::unique_ptr<RendererPrelauncher>> cache_;
diff --git a/chromecast/browser/lru_renderer_cache_test.cc b/chromecast/browser/lru_renderer_cache_test.cc
index 4d42de3..6ed903d 100644
--- a/chromecast/browser/lru_renderer_cache_test.cc
+++ b/chromecast/browser/lru_renderer_cache_test.cc
@@ -5,8 +5,10 @@
 #include "chromecast/browser/lru_renderer_cache.h"
 
 #include <memory>
+#include <utility>
 
 #include "base/memory/ptr_util.h"
+#include "chromecast/browser/renderer_config.h"
 #include "chromecast/browser/renderer_prelauncher.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/test/test_browser_context.h"
@@ -15,10 +17,12 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-#define EXPECT_CREATE_AND_PRELAUNCH(ptr, url)           \
-  ptr = new MockPrelauncher(&browser_context_, url);    \
-  EXPECT_CALL(*ptr, Prelaunch());                       \
-  EXPECT_CALL(factory_, Create(&browser_context_, url)) \
+#define EXPECT_CREATE_AND_PRELAUNCH(ptr, url)                      \
+  ptr = new MockPrelauncher(                                       \
+      &browser_context_,                                           \
+      renderer_config_manager_.CreateRendererConfigurator(), url); \
+  EXPECT_CALL(*ptr, Prelaunch());                                  \
+  EXPECT_CALL(factory_, Create(&browser_context_, url))            \
       .WillOnce(Return(ByMove(std::unique_ptr<MockPrelauncher>(ptr))));
 
 #define EXPECT_EVICTION(ptr) EXPECT_CALL(*ptr, Destroy());
@@ -43,8 +47,11 @@
 class MockPrelauncher : public RendererPrelauncher {
  public:
   MockPrelauncher(content::BrowserContext* browser_context,
+                  shell::RendererConfigurator renderer_configurator,
                   const GURL& page_url)
-      : RendererPrelauncher(browser_context, page_url) {}
+      : RendererPrelauncher(browser_context,
+                            std::move(renderer_configurator),
+                            page_url) {}
   virtual ~MockPrelauncher() { Destroy(); }
 
   MOCK_METHOD0(Prelaunch, void());
@@ -71,11 +78,13 @@
   content::TestBrowserThreadBundle threads_;
   content::TestBrowserContext browser_context_;
   MockFactory factory_;
+  shell::RendererConfigManager renderer_config_manager_;
   std::unique_ptr<LRURendererCache> lru_cache_;
 };
 
 TEST_F(LRURendererCacheTest, SimpleTakeAndRelease) {
-  lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
+  lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_,
+                                                  &renderer_config_manager_, 1);
   SetFactory();
   MockPrelauncher* p1;
   std::unique_ptr<RendererPrelauncher> taken;
@@ -110,7 +119,8 @@
 }
 
 TEST_F(LRURendererCacheTest, SimpleCacheEviction) {
-  lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
+  lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_,
+                                                  &renderer_config_manager_, 1);
   SetFactory();
   MockPrelauncher* p1;
   std::unique_ptr<RendererPrelauncher> taken;
@@ -135,7 +145,8 @@
 }
 
 TEST_F(LRURendererCacheTest, CapacityOne) {
-  lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
+  lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_,
+                                                  &renderer_config_manager_, 1);
   SetFactory();
   MockPrelauncher* p1;
   MockPrelauncher* p2;
@@ -222,7 +233,8 @@
 }
 
 TEST_F(LRURendererCacheTest, CapacityTwo) {
-  lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 2);
+  lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_,
+                                                  &renderer_config_manager_, 2);
   SetFactory();
   MockPrelauncher* p1;
   MockPrelauncher* p2;
diff --git a/chromecast/browser/renderer_config.cc b/chromecast/browser/renderer_config.cc
new file mode 100644
index 0000000..956a2dd
--- /dev/null
+++ b/chromecast/browser/renderer_config.cc
@@ -0,0 +1,154 @@
+// Copyright 2018 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 file.
+
+#include "chromecast/browser/renderer_config.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "content/public/common/child_process_host.h"
+
+namespace chromecast {
+namespace shell {
+
+namespace {
+
+class RendererConfigImpl : public RendererConfig {
+ public:
+  RendererConfigImpl(int render_process_id,
+                     base::flat_set<std::string> switches,
+                     base::flat_map<std::string, std::string> ascii_switches)
+      : render_process_id_(render_process_id),
+        switches_(std::move(switches)),
+        ascii_switches_(std::move(ascii_switches)) {
+    DCHECK_NE(content::ChildProcessHost::kInvalidUniqueID, render_process_id);
+  }
+
+  int GetRenderProcessId() const override { return render_process_id_; }
+
+  void AppendSwitchesTo(base::CommandLine* command_line) const override {
+    DCHECK(command_line);
+    for (const std::string& switch_string : switches_) {
+      command_line->AppendSwitch(switch_string);
+    }
+    for (const auto& ascii_switch : ascii_switches_) {
+      command_line->AppendSwitchASCII(ascii_switch.first, ascii_switch.second);
+    }
+  }
+
+ private:
+  ~RendererConfigImpl() override = default;
+
+  const int render_process_id_;
+  const base::flat_set<std::string> switches_;
+  const base::flat_map<std::string /* switch */, std::string /* value */>
+      ascii_switches_;
+
+  DISALLOW_COPY_AND_ASSIGN(RendererConfigImpl);
+};
+
+}  // namespace
+
+RendererConfig::RendererConfig() = default;
+RendererConfig::~RendererConfig() = default;
+
+RendererConfigurator::RendererConfigurator(
+    AddRendererConfigCallback add_renderer_config_callback,
+    RemoveRendererConfigCallback remove_renderer_config_callback)
+    : add_renderer_config_callback_(std::move(add_renderer_config_callback)),
+      remove_renderer_config_callback_(
+          std::move(remove_renderer_config_callback)) {
+  DCHECK(add_renderer_config_callback_);
+  DCHECK(remove_renderer_config_callback_);
+}
+
+RendererConfigurator::RendererConfigurator(RendererConfigurator&& other)
+    : add_renderer_config_callback_(
+          std::move(other.add_renderer_config_callback_)),
+      remove_renderer_config_callback_(
+          std::move(other.remove_renderer_config_callback_)),
+      render_process_id_(other.render_process_id_),
+      switches_(std::move(other.switches_)),
+      ascii_switches_(std::move(other.ascii_switches_)) {
+  other.render_process_id_ = content::ChildProcessHost::kInvalidUniqueID;
+}
+
+RendererConfigurator::~RendererConfigurator() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!add_renderer_config_callback_ && remove_renderer_config_callback_) {
+    std::move(remove_renderer_config_callback_).Run(render_process_id_);
+  }
+}
+
+void RendererConfigurator::Configure(int render_process_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(add_renderer_config_callback_);
+  DCHECK_NE(content::ChildProcessHost::kInvalidUniqueID, render_process_id);
+  render_process_id_ = render_process_id;
+  std::move(add_renderer_config_callback_)
+      .Run(render_process_id_, base::MakeRefCounted<RendererConfigImpl>(
+                                   render_process_id, std::move(switches_),
+                                   std::move(ascii_switches_)));
+}
+
+void RendererConfigurator::AppendSwitch(const std::string& switch_string) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(add_renderer_config_callback_);
+  switches_.insert(switch_string);
+}
+
+void RendererConfigurator::AppendSwitchASCII(const std::string& switch_string,
+                                             const std::string& value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(add_renderer_config_callback_);
+  ascii_switches_[switch_string] = value;
+}
+
+RendererConfigManager::RendererConfigManager() : weak_factory_(this) {}
+
+RendererConfigManager::~RendererConfigManager() = default;
+
+RendererConfigurator RendererConfigManager::CreateRendererConfigurator() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return RendererConfigurator(
+      base::BindOnce(&RendererConfigManager::AddRendererConfig,
+                     weak_factory_.GetWeakPtr()),
+      base::BindOnce(&RendererConfigManager::RemoveRendererConfig,
+                     weak_factory_.GetWeakPtr()));
+}
+
+scoped_refptr<const RendererConfig> RendererConfigManager::GetRendererConfig(
+    int render_process_id) {
+  if (render_process_id == content::ChildProcessHost::kInvalidUniqueID) {
+    return nullptr;
+  }
+  base::AutoLock lock(renderer_configs_lock_);
+  auto it = renderer_configs_.find(render_process_id);
+  if (it == renderer_configs_.end()) {
+    return nullptr;
+  }
+  return it->second;
+}
+
+void RendererConfigManager::AddRendererConfig(
+    int render_process_id,
+    scoped_refptr<RendererConfig> renderer_config) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_NE(content::ChildProcessHost::kInvalidUniqueID, render_process_id);
+  base::AutoLock lock(renderer_configs_lock_);
+  DCHECK_EQ(0U, renderer_configs_.count(render_process_id));
+  renderer_configs_.emplace(render_process_id, std::move(renderer_config));
+}
+
+void RendererConfigManager::RemoveRendererConfig(int render_process_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  base::AutoLock lock(renderer_configs_lock_);
+  DCHECK_NE(0U, renderer_configs_.count(render_process_id));
+  renderer_configs_.erase(render_process_id);
+}
+
+}  // namespace shell
+}  // namespace chromecast
diff --git a/chromecast/browser/renderer_config.h b/chromecast/browser/renderer_config.h
new file mode 100644
index 0000000..6639eb3a
--- /dev/null
+++ b/chromecast/browser/renderer_config.h
@@ -0,0 +1,120 @@
+// Copyright 2018 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 file.
+
+#ifndef CHROMECAST_BROWSER_RENDERER_CONFIG_H_
+#define CHROMECAST_BROWSER_RENDERER_CONFIG_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/synchronization/lock.h"
+
+namespace base {
+class CommandLine;
+}  // namespace base
+
+namespace chromecast {
+namespace shell {
+
+// Application-specific configuration for the renderer.
+// All methods are thread-safe.
+class RendererConfig : public base::RefCountedThreadSafe<RendererConfig> {
+ public:
+  REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+
+  RendererConfig();
+
+  // Returns the render process ID.
+  virtual int GetRenderProcessId() const = 0;
+
+  // Appends all switches to |command line|.
+  virtual void AppendSwitchesTo(base::CommandLine* command_line) const = 0;
+
+ protected:
+  virtual ~RendererConfig();
+
+ private:
+  friend class base::RefCountedThreadSafe<RendererConfig>;
+
+  DISALLOW_COPY_AND_ASSIGN(RendererConfig);
+};
+
+// Used to configure the renderer for individual applications.
+// All methods must be called on the main thread.
+class RendererConfigurator {
+ public:
+  using AddRendererConfigCallback =
+      base::OnceCallback<void(int render_process_id,
+                              scoped_refptr<RendererConfig> renderer_config)>;
+  using RemoveRendererConfigCallback =
+      base::OnceCallback<void(int render_process_id)>;
+
+  RendererConfigurator(
+      AddRendererConfigCallback add_renderer_config_callback,
+      RemoveRendererConfigCallback remove_renderer_config_callback);
+  RendererConfigurator(RendererConfigurator&& other);
+  virtual ~RendererConfigurator();
+
+  // Configures the renderer with |render_process_id|. Must only be called once,
+  // and no other methods may be called afterward. Must be called before the
+  // render process is started.
+  void Configure(int render_process_id);
+
+  // Appends a switch, with an optional value, to the command line.
+  void AppendSwitch(const std::string& switch_string);
+  void AppendSwitchASCII(const std::string& switch_string,
+                         const std::string& value);
+
+ private:
+  AddRendererConfigCallback add_renderer_config_callback_;
+  RemoveRendererConfigCallback remove_renderer_config_callback_;
+  int render_process_id_;
+  base::flat_set<std::string> switches_;
+  base::flat_map<std::string /* switch */, std::string /* value */>
+      ascii_switches_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(RendererConfigurator);
+};
+
+class RendererConfigManager {
+ public:
+  RendererConfigManager();
+  ~RendererConfigManager();
+
+  // Returns a new renderer configurator.
+  // Must be called on the main thread.
+  RendererConfigurator CreateRendererConfigurator();
+
+  // Returns the config for the renderer with |render_process_id|.
+  // May be called on any thread.
+  scoped_refptr<const RendererConfig> GetRendererConfig(int render_process_id);
+
+ private:
+  void AddRendererConfig(int render_process_id,
+                         scoped_refptr<RendererConfig> renderer_config);
+  void RemoveRendererConfig(int render_process_id);
+
+  base::flat_map<int /* render_process_id */, scoped_refptr<RendererConfig>>
+      renderer_configs_;
+  base::Lock renderer_configs_lock_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  base::WeakPtrFactory<RendererConfigManager> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(RendererConfigManager);
+};
+
+}  // namespace shell
+}  // namespace chromecast
+
+#endif  // CHROMECAST_BROWSER_RENDERER_CONFIG_H_
diff --git a/chromecast/browser/renderer_config_unittest.cc b/chromecast/browser/renderer_config_unittest.cc
new file mode 100644
index 0000000..3507630
--- /dev/null
+++ b/chromecast/browser/renderer_config_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright 2018 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 file.
+
+#include "chromecast/browser/renderer_config.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromecast {
+namespace shell {
+
+namespace {
+
+constexpr char kSwitch1[] = "switch1";
+constexpr char kSwitch2[] = "switch2";
+constexpr char kValue[] = "value";
+constexpr int kRenderProcessId = 123;
+
+}  // namespace
+
+TEST(RendererConfigTest, AppendCommandLineSwitches) {
+  RendererConfigManager manager;
+  ASSERT_FALSE(manager.GetRendererConfig(kRenderProcessId));
+  scoped_refptr<const RendererConfig> config;
+  {
+    auto configurator = manager.CreateRendererConfigurator();
+    configurator.AppendSwitch(kSwitch1);
+    configurator.AppendSwitchASCII(kSwitch2, kValue);
+    configurator.Configure(kRenderProcessId);
+    config = manager.GetRendererConfig(kRenderProcessId);
+    ASSERT_TRUE(config);
+  }
+  EXPECT_FALSE(manager.GetRendererConfig(kRenderProcessId));
+  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+  config->AppendSwitchesTo(&command_line);
+  EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
+  EXPECT_TRUE(command_line.HasSwitch(kSwitch2));
+  EXPECT_EQ(kValue, command_line.GetSwitchValueASCII(kSwitch2));
+}
+
+TEST(RendererConfigTest, ConfiguratorOutlivesManager) {
+  auto manager = std::make_unique<RendererConfigManager>();
+  ASSERT_FALSE(manager->GetRendererConfig(kRenderProcessId));
+  auto configurator = manager->CreateRendererConfigurator();
+  configurator.Configure(kRenderProcessId);
+  EXPECT_TRUE(manager->GetRendererConfig(kRenderProcessId));
+  manager.reset();
+}
+
+TEST(RendererConfigTest, ConfigureAfterManagerDestroyed) {
+  auto manager = std::make_unique<RendererConfigManager>();
+  auto configurator = manager->CreateRendererConfigurator();
+  manager.reset();
+  configurator.Configure(kRenderProcessId);
+}
+
+}  // namespace shell
+}  // namespace chromecast
diff --git a/chromecast/browser/renderer_prelauncher.cc b/chromecast/browser/renderer_prelauncher.cc
index 66f3a14..c5ff082 100644
--- a/chromecast/browser/renderer_prelauncher.cc
+++ b/chromecast/browser/renderer_prelauncher.cc
@@ -4,6 +4,8 @@
 
 #include "chromecast/browser/renderer_prelauncher.h"
 
+#include <utility>
+
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/common/child_process_host.h"
@@ -12,8 +14,10 @@
 
 RendererPrelauncher::RendererPrelauncher(
     content::BrowserContext* browser_context,
+    shell::RendererConfigurator renderer_configurator,
     const GURL& gurl)
     : browser_context_(browser_context),
+      renderer_configurator_(std::move(renderer_configurator)),
       gurl_(gurl),
       rph_routing_id_(MSG_ROUTING_NONE) {}
 
@@ -27,6 +31,7 @@
 void RendererPrelauncher::Prelaunch() {
   DLOG(INFO) << "Prelaunching for: " << gurl_;
   site_instance_ = content::SiteInstance::CreateForURL(browser_context_, gurl_);
+  renderer_configurator_.Configure(site_instance_->GetProcess()->GetID());
   content::RenderProcessHost* rph = site_instance_->GetProcess();
   rph_routing_id_ = rph->GetNextRoutingID();
   rph->AddRoute(rph_routing_id_, this);
diff --git a/chromecast/browser/renderer_prelauncher.h b/chromecast/browser/renderer_prelauncher.h
index a1cfc34f..bce85da 100644
--- a/chromecast/browser/renderer_prelauncher.h
+++ b/chromecast/browser/renderer_prelauncher.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "chromecast/browser/renderer_config.h"
 #include "ipc/ipc_listener.h"
 #include "url/gurl.h"
 
@@ -14,7 +15,7 @@
 class BrowserContext;
 class RenderProcessHost;
 class SiteInstance;
-}
+}  // namespace content
 
 namespace chromecast {
 
@@ -25,6 +26,7 @@
 class RendererPrelauncher : private IPC::Listener {
  public:
   RendererPrelauncher(content::BrowserContext* browser_context,
+                      shell::RendererConfigurator renderer_configurator,
                       const GURL& gurl);
   ~RendererPrelauncher() override;
 
@@ -41,6 +43,7 @@
   bool OnMessageReceived(const IPC::Message& message) override;
 
   content::BrowserContext* const browser_context_;
+  shell::RendererConfigurator renderer_configurator_;
   scoped_refptr<content::SiteInstance> site_instance_;
   const GURL gurl_;
   int32_t rph_routing_id_;
diff --git a/chromecast/browser/renderer_prelauncher_test.cc b/chromecast/browser/renderer_prelauncher_test.cc
index f1e93e5..9157bdf 100644
--- a/chromecast/browser/renderer_prelauncher_test.cc
+++ b/chromecast/browser/renderer_prelauncher_test.cc
@@ -13,6 +13,7 @@
 #include "chromecast/base/metrics/cast_metrics_helper.h"
 #include "chromecast/browser/cast_browser_context.h"
 #include "chromecast/browser/cast_browser_process.h"
+#include "chromecast/browser/renderer_config.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
@@ -59,8 +60,10 @@
   EXPECT_TRUE(browser_context);
 
   // Prelaunch a renderer process for the url.
-  std::unique_ptr<RendererPrelauncher> prelauncher(
-      new RendererPrelauncher(browser_context, gurl));
+  shell::RendererConfigManager renderer_config_manager;
+  auto prelauncher = std::make_unique<RendererPrelauncher>(
+      browser_context, renderer_config_manager.CreateRendererConfigurator(),
+      gurl);
   prelauncher->Prelaunch();
   scoped_refptr<content::SiteInstance> site_instance =
       prelauncher->site_instance();