// Copyright (c) 2013 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 "content/child/child_shared_bitmap_manager.h" #include #include #include "base/debug/alias.h" #include "base/process/memory.h" #include "base/process/process_metrics.h" #include "build/build_config.h" #include "content/child/child_thread_impl.h" #include "content/common/child_process_messages.h" #include "ui/gfx/geometry/size.h" namespace content { namespace { class ChildSharedBitmap : public SharedMemoryBitmap { public: ChildSharedBitmap(scoped_refptr sender, base::SharedMemory* shared_memory, const cc::SharedBitmapId& id) : SharedMemoryBitmap(static_cast(shared_memory->memory()), id, shared_memory), sender_(sender) {} ChildSharedBitmap(scoped_refptr sender, scoped_ptr shared_memory_holder, const cc::SharedBitmapId& id) : ChildSharedBitmap(sender, shared_memory_holder.get(), id) { shared_memory_holder_ = std::move(shared_memory_holder); } ~ChildSharedBitmap() override { sender_->Send(new ChildProcessHostMsg_DeletedSharedBitmap(id())); } private: scoped_refptr sender_; scoped_ptr shared_memory_holder_; }; // Collect extra information for debugging bitmap creation failures. void CollectMemoryUsageAndDie(const gfx::Size& size, size_t alloc_size) { #if defined(OS_WIN) int width = size.width(); int height = size.height(); DWORD last_error = GetLastError(); scoped_ptr metrics( base::ProcessMetrics::CreateProcessMetrics( base::GetCurrentProcessHandle())); size_t private_bytes = 0; size_t shared_bytes = 0; metrics->GetMemoryBytes(&private_bytes, &shared_bytes); base::debug::Alias(&width); base::debug::Alias(&height); base::debug::Alias(&last_error); base::debug::Alias(&private_bytes); base::debug::Alias(&shared_bytes); #endif base::TerminateBecauseOutOfMemory(alloc_size); } } // namespace SharedMemoryBitmap::SharedMemoryBitmap(uint8_t* pixels, const cc::SharedBitmapId& id, base::SharedMemory* shared_memory) : SharedBitmap(pixels, id), shared_memory_(shared_memory) {} ChildSharedBitmapManager::ChildSharedBitmapManager( scoped_refptr sender) : sender_(sender) { } ChildSharedBitmapManager::~ChildSharedBitmapManager() {} scoped_ptr ChildSharedBitmapManager::AllocateSharedBitmap( const gfx::Size& size) { scoped_ptr bitmap = AllocateSharedMemoryBitmap(size); #if defined(OS_POSIX) // Close file descriptor to avoid running out. if (bitmap) bitmap->shared_memory()->Close(); #endif return std::move(bitmap); } scoped_ptr ChildSharedBitmapManager::AllocateSharedMemoryBitmap(const gfx::Size& size) { TRACE_EVENT2("renderer", "ChildSharedBitmapManager::AllocateSharedMemoryBitmap", "width", size.width(), "height", size.height()); size_t memory_size; if (!cc::SharedBitmap::SizeInBytes(size, &memory_size)) return scoped_ptr(); cc::SharedBitmapId id = cc::SharedBitmap::GenerateId(); scoped_ptr memory; #if defined(OS_POSIX) base::SharedMemoryHandle handle; sender_->Send(new ChildProcessHostMsg_SyncAllocateSharedBitmap( memory_size, id, &handle)); memory = make_scoped_ptr(new base::SharedMemory(handle, false)); if (!memory->Map(memory_size)) CollectMemoryUsageAndDie(size, memory_size); #else memory = ChildThreadImpl::AllocateSharedMemory(memory_size, sender_.get()); if (!memory) CollectMemoryUsageAndDie(size, memory_size); if (!memory->Map(memory_size)) CollectMemoryUsageAndDie(size, memory_size); base::SharedMemoryHandle handle_to_send = memory->handle(); sender_->Send(new ChildProcessHostMsg_AllocatedSharedBitmap( memory_size, handle_to_send, id)); #endif return make_scoped_ptr(new ChildSharedBitmap(sender_, std::move(memory), id)); } scoped_ptr ChildSharedBitmapManager::GetSharedBitmapFromId( const gfx::Size&, const cc::SharedBitmapId&) { NOTREACHED(); return scoped_ptr(); } scoped_ptr ChildSharedBitmapManager::GetBitmapForSharedMemory( base::SharedMemory* mem) { cc::SharedBitmapId id = cc::SharedBitmap::GenerateId(); base::SharedMemoryHandle handle_to_send = mem->handle(); #if defined(OS_POSIX) if (!mem->ShareToProcess(base::GetCurrentProcessHandle(), &handle_to_send)) return scoped_ptr(); #endif sender_->Send(new ChildProcessHostMsg_AllocatedSharedBitmap( mem->mapped_size(), handle_to_send, id)); return make_scoped_ptr(new ChildSharedBitmap(sender_, mem, id)); } } // namespace content