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