| Index: components/discardable_memory/service/discardable_shared_memory_manager.cc
 | 
| diff --git a/components/discardable_memory/service/discardable_shared_memory_manager.cc b/components/discardable_memory/service/discardable_shared_memory_manager.cc
 | 
| index 1036dc84d697ed5324d2f181a15b7b618cdddf46..6f5bf1cf2ec0088ec54282df7e9c659ea079f167 100644
 | 
| --- a/components/discardable_memory/service/discardable_shared_memory_manager.cc
 | 
| +++ b/components/discardable_memory/service/discardable_shared_memory_manager.cc
 | 
| @@ -29,6 +29,8 @@
 | 
|  #include "base/trace_event/trace_event.h"
 | 
|  #include "build/build_config.h"
 | 
|  #include "components/discardable_memory/common/discardable_shared_memory_heap.h"
 | 
| +#include "mojo/public/cpp/bindings/strong_binding.h"
 | 
| +#include "mojo/public/cpp/system/platform_handle.h"
 | 
|  
 | 
|  #if defined(OS_LINUX)
 | 
|  #include "base/files/file_path.h"
 | 
| @@ -57,6 +59,48 @@ uint64_t ClientProcessUniqueIdToTracingProcessId(int client_id) {
 | 
|           1;
 | 
|  }
 | 
|  
 | 
| +// mojom::DiscardableSharedMemoryManager implementation. It contains the
 | 
| +// |client_id_| which is not visible to client. We associate allocations with a
 | 
| +// given mojo instance, so if the instance is closed, we can release the
 | 
| +// allocations associated with that instance.
 | 
| +class MojoDiscardableSharedMemoryManagerImpl
 | 
| +    : public mojom::DiscardableSharedMemoryManager {
 | 
| + public:
 | 
| +  MojoDiscardableSharedMemoryManagerImpl(
 | 
| +      int32_t client_id,
 | 
| +      ::discardable_memory::DiscardableSharedMemoryManager* manager)
 | 
| +      : client_id_(client_id), manager_(manager) {}
 | 
| +
 | 
| +  ~MojoDiscardableSharedMemoryManagerImpl() override {
 | 
| +    // Remove this client from the |manager_|, so all allocated discardable
 | 
| +    // memory belong to this client will be released.
 | 
| +    manager_->ClientRemoved(client_id_);
 | 
| +  }
 | 
| +
 | 
| +  // mojom::DiscardableSharedMemoryManager overrides:
 | 
| +  void AllocateLockedDiscardableSharedMemory(
 | 
| +      uint32_t size,
 | 
| +      int32_t id,
 | 
| +      const AllocateLockedDiscardableSharedMemoryCallback& callback) override {
 | 
| +    base::SharedMemoryHandle handle;
 | 
| +    manager_->AllocateLockedDiscardableSharedMemoryForClient(client_id_, size,
 | 
| +                                                             id, &handle);
 | 
| +    mojo::ScopedSharedBufferHandle memory =
 | 
| +        mojo::WrapSharedMemoryHandle(handle, size, false /* read_only */);
 | 
| +    return callback.Run(std::move(memory));
 | 
| +  }
 | 
| +
 | 
| +  void DeletedDiscardableSharedMemory(int32_t id) override {
 | 
| +    manager_->ClientDeletedDiscardableSharedMemory(id, client_id_);
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  const int32_t client_id_;
 | 
| +  ::discardable_memory::DiscardableSharedMemoryManager* const manager_;
 | 
| +
 | 
| +  DISALLOW_COPY_AND_ASSIGN(MojoDiscardableSharedMemoryManagerImpl);
 | 
| +};
 | 
| +
 | 
|  class DiscardableMemoryImpl : public base::DiscardableMemory {
 | 
|   public:
 | 
|    DiscardableMemoryImpl(
 | 
| @@ -180,7 +224,8 @@ DiscardableSharedMemoryManager::MemorySegment::MemorySegment(
 | 
|  DiscardableSharedMemoryManager::MemorySegment::~MemorySegment() {}
 | 
|  
 | 
|  DiscardableSharedMemoryManager::DiscardableSharedMemoryManager()
 | 
| -    : default_memory_limit_(GetDefaultMemoryLimit()),
 | 
| +    : next_client_id_(1),
 | 
| +      default_memory_limit_(GetDefaultMemoryLimit()),
 | 
|        memory_limit_(default_memory_limit_),
 | 
|        bytes_allocated_(0),
 | 
|        memory_pressure_listener_(new base::MemoryPressureListener(
 | 
| @@ -205,23 +250,38 @@ DiscardableSharedMemoryManager::~DiscardableSharedMemoryManager() {
 | 
|        this);
 | 
|  }
 | 
|  
 | 
| -DiscardableSharedMemoryManager* DiscardableSharedMemoryManager::current() {
 | 
| +// static
 | 
| +DiscardableSharedMemoryManager*
 | 
| +DiscardableSharedMemoryManager::CreateInstance() {
 | 
| +  DCHECK(g_discardable_shared_memory_manager == nullptr);
 | 
| +  return g_discardable_shared_memory_manager.Pointer();
 | 
| +}
 | 
| +
 | 
| +// static
 | 
| +DiscardableSharedMemoryManager* DiscardableSharedMemoryManager::GetInstance() {
 | 
| +  DCHECK(!(g_discardable_shared_memory_manager == nullptr));
 | 
|    return g_discardable_shared_memory_manager.Pointer();
 | 
|  }
 | 
|  
 | 
| +void DiscardableSharedMemoryManager::Bind(
 | 
| +    mojom::DiscardableSharedMemoryManagerRequest request) {
 | 
| +  mojo::MakeStrongBinding(
 | 
| +      base::MakeUnique<MojoDiscardableSharedMemoryManagerImpl>(
 | 
| +          next_client_id_++, this),
 | 
| +      std::move(request));
 | 
| +}
 | 
| +
 | 
|  std::unique_ptr<base::DiscardableMemory>
 | 
|  DiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(size_t size) {
 | 
|    DCHECK_NE(size, 0u);
 | 
|  
 | 
| -  DiscardableSharedMemoryId new_id =
 | 
| -      g_next_discardable_shared_memory_id.GetNext();
 | 
| -  base::ProcessHandle current_process_handle = base::GetCurrentProcessHandle();
 | 
| +  int32_t new_id = g_next_discardable_shared_memory_id.GetNext();
 | 
|  
 | 
|    // Note: Use DiscardableSharedMemoryHeap for in-process allocation
 | 
|    // of discardable memory if the cost of each allocation is too high.
 | 
|    base::SharedMemoryHandle handle;
 | 
| -  AllocateLockedDiscardableSharedMemory(
 | 
| -      current_process_handle, kInvalidUniqueClientID, size, new_id, &handle);
 | 
| +  AllocateLockedDiscardableSharedMemory(kInvalidUniqueClientID, size, new_id,
 | 
| +                                        &handle);
 | 
|    std::unique_ptr<base::DiscardableSharedMemory> memory(
 | 
|        new base::DiscardableSharedMemory(handle));
 | 
|    if (!memory->Map(size))
 | 
| @@ -308,17 +368,16 @@ bool DiscardableSharedMemoryManager::OnMemoryDump(
 | 
|  
 | 
|  void DiscardableSharedMemoryManager::
 | 
|      AllocateLockedDiscardableSharedMemoryForClient(
 | 
| -        base::ProcessHandle process_handle,
 | 
|          int client_id,
 | 
|          size_t size,
 | 
| -        DiscardableSharedMemoryId id,
 | 
| +        int32_t id,
 | 
|          base::SharedMemoryHandle* shared_memory_handle) {
 | 
| -  AllocateLockedDiscardableSharedMemory(process_handle, client_id, size, id,
 | 
| +  AllocateLockedDiscardableSharedMemory(client_id, size, id,
 | 
|                                          shared_memory_handle);
 | 
|  }
 | 
|  
 | 
|  void DiscardableSharedMemoryManager::ClientDeletedDiscardableSharedMemory(
 | 
| -    DiscardableSharedMemoryId id,
 | 
| +    int32_t id,
 | 
|      int client_id) {
 | 
|    DeletedDiscardableSharedMemory(id, client_id);
 | 
|  }
 | 
| @@ -380,10 +439,9 @@ void DiscardableSharedMemoryManager::OnMemoryStateChange(
 | 
|  }
 | 
|  
 | 
|  void DiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
 | 
| -    base::ProcessHandle process_handle,
 | 
|      int client_id,
 | 
|      size_t size,
 | 
| -    DiscardableSharedMemoryId id,
 | 
| +    int32_t id,
 | 
|      base::SharedMemoryHandle* shared_memory_handle) {
 | 
|    base::AutoLock lock(lock_);
 | 
|  
 | 
| @@ -416,15 +474,6 @@ void DiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  if (!memory->ShareToProcess(process_handle, shared_memory_handle)) {
 | 
| -    LOG(ERROR) << "Cannot share discardable memory segment";
 | 
| -    *shared_memory_handle = base::SharedMemory::NULLHandle();
 | 
| -    return;
 | 
| -  }
 | 
| -
 | 
| -  // Close file descriptor to avoid running out.
 | 
| -  memory->Close();
 | 
| -
 | 
|    base::CheckedNumeric<size_t> checked_bytes_allocated = bytes_allocated_;
 | 
|    checked_bytes_allocated += memory->mapped_size();
 | 
|    if (!checked_bytes_allocated.IsValid()) {
 | 
| @@ -435,6 +484,10 @@ void DiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
 | 
|    bytes_allocated_ = checked_bytes_allocated.ValueOrDie();
 | 
|    BytesAllocatedChanged(bytes_allocated_);
 | 
|  
 | 
| +  *shared_memory_handle = base::SharedMemory::DuplicateHandle(memory->handle());
 | 
| +  // Close file descriptor to avoid running out.
 | 
| +  memory->Close();
 | 
| +
 | 
|    scoped_refptr<MemorySegment> segment(new MemorySegment(std::move(memory)));
 | 
|    client_segments[id] = segment.get();
 | 
|    segments_.push_back(segment.get());
 | 
| @@ -445,7 +498,7 @@ void DiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
 | 
|  }
 | 
|  
 | 
|  void DiscardableSharedMemoryManager::DeletedDiscardableSharedMemory(
 | 
| -    DiscardableSharedMemoryId id,
 | 
| +    int32_t id,
 | 
|      int client_id) {
 | 
|    base::AutoLock lock(lock_);
 | 
|  
 | 
| 
 |