text: // 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 COMPONENTS_HEAP_PROFILING_CLIENT_CONNECTION_MANAGER_H_
  #define COMPONENTS_HEAP_PROFILING_CLIENT_CONNECTION_MANAGER_H_
  
  #include <unordered_set>
  
  #include "base/gtest_prod_util.h"
  #include "base/macros.h"
  #include "base/memory/weak_ptr.h"
  #include "content/public/browser/browser_child_process_observer.h"
  #include "content/public/browser/child_process_data.h"
  #include "content/public/browser/notification_observer.h"
  #include "content/public/browser/notification_registrar.h"
  
  namespace content {
  class RenderProcessHost;
  }  // namespace content
  
  namespace heap_profiling {
  
  class Controller;
  enum class Mode;
  
  // This class is responsible for connecting HeapProfilingClients to the
  // HeapProfilingService.
  //   * It registers itself as a content::NotificationObserver to listen for the
  //     creation of the renderer processes.
  //   * It registers itself as a content::BrowserChildProcessObserver to listen
  //     for the creation of non-renderer processes.
  // When a new process is created, it checks the current |Mode| to see whether
  // the process should be profiled. If so, it grabs the HeapProfilingClient from
  // the newly created process and connects it to the HeapProfilingService.
  //
  // This class is intended to be used from the browser/privileged process of the
  // embedder.
  //
  // This class must be constructed/accessed/destroyed from the UI thread.
  //
  // This class can be subclassed for exactly one reason: to allow embedders to
  // override AllowedToProfileRenderer in order to prevent incognito renderers
  // from being profiled.
  class ClientConnectionManager : public content::BrowserChildProcessObserver,
                                  content::NotificationObserver {
   public:
    // The owner of this instance must guarantee that |controller_| outlives this
    // class.
    // |controller| must be bound to the IO thread.
    ClientConnectionManager(base::WeakPtr<Controller> controller, Mode mode);
    ~ClientConnectionManager() override;
  
    // Start must be called immediately after the constructor. The only reason
    // that this is not a part of the constructor is to allow tests to skip this
    // step.
    void Start();
  
    Mode GetMode();
  
    // In additional to profiling |pid|, this will change the Mode to kManual.
    // From here on out, the caller must manually specify processes to be
    // profiled.
    void StartProfilingProcess(base::ProcessId pid);
  
    virtual bool AllowedToProfileRenderer(content::RenderProcessHost* host);
  
   private:
    FRIEND_TEST_ALL_PREFIXES(ChromeClientConnectionManager,
                             ShouldProfileNewRenderer);
  
    // Exists for testing only.
    void SetModeForTesting(Mode mode);
  
    // New processes will be profiled as they are created. Existing processes msut
    // be manually checked upon creation.
    void StartProfilingExistingProcessesIfNecessary();
  
    // BrowserChildProcessObserver
    // Observe connection of non-renderer child processes.
    void BrowserChildProcessLaunchedAndConnected(
        const content::ChildProcessData& data) override;
  
    void StartProfilingNonRendererChild(const content::ChildProcessData& data);
  
    // NotificationObserver
    // Observe connection of renderer child processes.
    void Observe(int type,
                 const content::NotificationSource& source,
                 const content::NotificationDetails& details) override;
  
    bool ShouldProfileNewRenderer(content::RenderProcessHost* renderer);
  
    void StartProfilingRenderer(content::RenderProcessHost* renderer);
  
    // The owner of this instance must guarantee that |controller_| outlives this
    // class.
    // |controller_| must be bound to the IO thread.
    base::WeakPtr<Controller> controller_;
  
    Mode mode_;
    content::NotificationRegistrar registrar_;
  
    // This is used to identify the currently profiled renderers. Elements should
    // only be accessed on the UI thread and their values should be considered
    // opaque.
    //
    // Semantically, the elements must be something that identifies which
    // specific RenderProcess is being profiled. When the underlying RenderProcess
    // goes away, the element must be removed. The RenderProcessHost
    // pointer and the NOTIFICATION_RENDERER_PROCESS_CREATED notification can be
    // used to provide these semantics.
    //
    // This variable represents renderers that have been instructed to start
    // profiling - it does not reflect whether a renderer is currently still being
    // profiled. That information is only known by the profiling service, and for
    // simplicity, it's easier to just track this variable in this process.
    std::unordered_set<void*> profiled_renderers_;
  
    DISALLOW_COPY_AND_ASSIGN(ClientConnectionManager);
  };
  
  }  // namespace heap_profiling
  
  #endif  // COMPONENTS_HEAP_PROFILING_CLIENT_CONNECTION_MANAGER_H_
  