1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/command_line.h" 6#include "base/memory/discardable_memory.h" 7#include "base/memory/scoped_vector.h" 8#include "content/public/browser/content_browser_client.h" 9#include "content/public/common/content_client.h" 10#include "content/public/common/content_switches.h" 11#include "content/public/renderer/content_renderer_client.h" 12#include "content/renderer/render_process_impl.h" 13#include "content/renderer/render_thread_impl.h" 14#include "content/test/mock_render_process.h" 15#include "testing/gtest/include/gtest/gtest.h" 16 17namespace content { 18namespace { 19 20class RenderThreadImplBrowserTest : public testing::Test { 21 public: 22 virtual ~RenderThreadImplBrowserTest() {} 23}; 24 25class DummyListener : public IPC::Listener { 26 public: 27 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 28 return true; 29 } 30}; 31 32void CheckRenderThreadInputHandlerManager(RenderThreadImpl* thread) { 33 ASSERT_TRUE(thread->input_handler_manager()); 34} 35 36// Check that InputHandlerManager outlives compositor thread because it uses 37// raw pointers to post tasks. 38// Disabled under LeakSanitizer due to memory leaks. http://crbug.com/348994 39#if defined(LEAK_SANITIZER) 40#define MAYBE_InputHandlerManagerDestroyedAfterCompositorThread \ 41 DISABLED_InputHandlerManagerDestroyedAfterCompositorThread 42#else 43#define MAYBE_InputHandlerManagerDestroyedAfterCompositorThread \ 44 InputHandlerManagerDestroyedAfterCompositorThread 45#endif 46TEST_F(RenderThreadImplBrowserTest, 47 MAYBE_InputHandlerManagerDestroyedAfterCompositorThread) { 48 ContentClient content_client; 49 ContentBrowserClient content_browser_client; 50 ContentRendererClient content_renderer_client; 51 SetContentClient(&content_client); 52 SetBrowserClientForTesting(&content_browser_client); 53 SetRendererClientForTesting(&content_renderer_client); 54 base::MessageLoopForIO message_loop_; 55 56 std::string channel_id = IPC::Channel::GenerateVerifiedChannelID( 57 std::string()); 58 DummyListener dummy_listener; 59 scoped_ptr<IPC::Channel> channel( 60 IPC::Channel::CreateServer(channel_id, &dummy_listener)); 61 ASSERT_TRUE(channel->Connect()); 62 63 scoped_ptr<MockRenderProcess> mock_process(new MockRenderProcess); 64 // Owned by mock_process. 65 RenderThreadImpl* thread = new RenderThreadImpl(channel_id); 66 thread->EnsureWebKitInitialized(); 67 68 ASSERT_TRUE(thread->input_handler_manager()); 69 70 thread->compositor_message_loop_proxy()->PostTask( 71 FROM_HERE, 72 base::Bind(&CheckRenderThreadInputHandlerManager, thread)); 73} 74 75// Checks that emulated discardable memory is discarded when the last widget 76// is hidden. 77// Disabled under LeakSanitizer due to memory leaks. 78#if defined(LEAK_SANITIZER) 79#define MAYBE_EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden \ 80 DISABLED_EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden 81#else 82#define MAYBE_EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden \ 83 EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden 84#endif 85TEST_F(RenderThreadImplBrowserTest, 86 MAYBE_EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden) { 87 ContentClient content_client; 88 ContentBrowserClient content_browser_client; 89 ContentRendererClient content_renderer_client; 90 SetContentClient(&content_client); 91 SetBrowserClientForTesting(&content_browser_client); 92 SetRendererClientForTesting(&content_renderer_client); 93 base::MessageLoopForIO message_loop_; 94 95 std::string channel_id = 96 IPC::Channel::GenerateVerifiedChannelID(std::string()); 97 DummyListener dummy_listener; 98 scoped_ptr<IPC::Channel> channel( 99 IPC::Channel::CreateServer(channel_id, &dummy_listener)); 100 ASSERT_TRUE(channel->Connect()); 101 102 scoped_ptr<MockRenderProcess> mock_process(new MockRenderProcess); 103 // Owned by mock_process. 104 RenderThreadImpl* thread = new RenderThreadImpl(channel_id); 105 thread->EnsureWebKitInitialized(); 106 thread->WidgetCreated(); 107 108 // Allocate 128MB of discardable memory. 109 ScopedVector<base::DiscardableMemory> discardable_memory; 110 for (int i = 0; i < 32; ++i) { 111 discardable_memory.push_back( 112 base::DiscardableMemory::CreateLockedMemoryWithType( 113 base::DISCARDABLE_MEMORY_TYPE_EMULATED, 4 * 1024 * 1024).release()); 114 ASSERT_TRUE(discardable_memory.back()); 115 discardable_memory.back()->Unlock(); 116 } 117 118 // Hide all widgets. 119 thread->WidgetHidden(); 120 121 // Count how much memory is left, should be at most one block. 122 int blocks_left = 0; 123 for (auto iter = discardable_memory.begin(); iter != discardable_memory.end(); 124 ++iter) { 125 if ((*iter)->Lock() == base::DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS) 126 ++blocks_left; 127 } 128 EXPECT_LE(blocks_left, 1); 129 130 thread->WidgetDestroyed(); 131} 132 133} // namespace 134} // namespace content 135