1 // Copyright (c) 2012 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 "content/public/test/mock_render_process_host.h" 6 7 #include "base/lazy_instance.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/time/time.h" 10 #include "content/browser/child_process_security_policy_impl.h" 11 #include "content/browser/renderer_host/render_process_host_impl.h" 12 #include "content/browser/renderer_host/render_view_host_impl.h" 13 #include "content/browser/renderer_host/render_widget_host_impl.h" 14 #include "content/common/child_process_host_impl.h" 15 #include "content/public/browser/notification_service.h" 16 #include "content/public/browser/notification_types.h" 17 #include "content/public/browser/storage_partition.h" 18 19 namespace content { 20 21 MockRenderProcessHost::MockRenderProcessHost( 22 BrowserContext* browser_context) 23 : transport_dib_(NULL), 24 bad_msg_count_(0), 25 factory_(NULL), 26 id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), 27 browser_context_(browser_context), 28 fast_shutdown_started_(false) { 29 // Child process security operations can't be unit tested unless we add 30 // ourselves as an existing child process. 31 ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID()); 32 33 RenderProcessHostImpl::RegisterHost(GetID(), this); 34 } 35 36 MockRenderProcessHost::~MockRenderProcessHost() { 37 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID()); 38 delete transport_dib_; 39 if (factory_) 40 factory_->Remove(this); 41 // In unit tests, Release() might not have been called. 42 RenderProcessHostImpl::UnregisterHost(GetID()); 43 } 44 45 void MockRenderProcessHost::EnableSendQueue() { 46 } 47 48 bool MockRenderProcessHost::Init() { 49 return true; 50 } 51 52 int MockRenderProcessHost::GetNextRoutingID() { 53 static int prev_routing_id = 0; 54 return ++prev_routing_id; 55 } 56 57 void MockRenderProcessHost::AddRoute( 58 int32 routing_id, 59 IPC::Listener* listener) { 60 listeners_.AddWithID(listener, routing_id); 61 } 62 63 void MockRenderProcessHost::RemoveRoute(int32 routing_id) { 64 DCHECK(listeners_.Lookup(routing_id) != NULL); 65 listeners_.Remove(routing_id); 66 Cleanup(); 67 } 68 69 bool MockRenderProcessHost::WaitForBackingStoreMsg( 70 int render_widget_id, 71 const base::TimeDelta& max_delay, 72 IPC::Message* msg) { 73 return false; 74 } 75 76 void MockRenderProcessHost::ReceivedBadMessage() { 77 ++bad_msg_count_; 78 } 79 80 void MockRenderProcessHost::WidgetRestored() { 81 } 82 83 void MockRenderProcessHost::WidgetHidden() { 84 } 85 86 int MockRenderProcessHost::VisibleWidgetCount() const { 87 return 1; 88 } 89 90 bool MockRenderProcessHost::IsGuest() const { 91 return false; 92 } 93 94 StoragePartition* MockRenderProcessHost::GetStoragePartition() const { 95 return NULL; 96 } 97 98 void MockRenderProcessHost::AddWord(const string16& word) { 99 } 100 101 bool MockRenderProcessHost::FastShutdownIfPossible() { 102 // We aren't actually going to do anything, but set |fast_shutdown_started_| 103 // to true so that tests know we've been called. 104 fast_shutdown_started_ = true; 105 return true; 106 } 107 108 bool MockRenderProcessHost::FastShutdownStarted() const { 109 return fast_shutdown_started_; 110 } 111 112 void MockRenderProcessHost::DumpHandles() { 113 } 114 115 base::ProcessHandle MockRenderProcessHost::GetHandle() const { 116 // Return the current-process handle for the IPC::GetFileHandleForProcess 117 // function. 118 return base::Process::Current().handle(); 119 } 120 121 bool MockRenderProcessHost::Send(IPC::Message* msg) { 122 // Save the message in the sink. 123 sink_.OnMessageReceived(*msg); 124 delete msg; 125 return true; 126 } 127 128 TransportDIB* MockRenderProcessHost::MapTransportDIB(TransportDIB::Id dib_id) { 129 #if defined(OS_WIN) 130 HANDLE duped; 131 DuplicateHandle(GetCurrentProcess(), dib_id.handle, GetCurrentProcess(), 132 &duped, 0, TRUE, DUPLICATE_SAME_ACCESS); 133 return TransportDIB::Map(duped); 134 #elif defined(TOOLKIT_GTK) 135 return TransportDIB::Map(dib_id.shmkey); 136 #elif defined(OS_ANDROID) 137 // On Android, Handles and Ids are the same underlying type. 138 return TransportDIB::Map(dib_id); 139 #else 140 // On POSIX, TransportDIBs are always created in the browser, so we cannot map 141 // one from a dib_id. 142 return TransportDIB::Create(100 * 100 * 4, 0); 143 #endif 144 } 145 146 TransportDIB* MockRenderProcessHost::GetTransportDIB(TransportDIB::Id dib_id) { 147 if (transport_dib_) 148 return transport_dib_; 149 150 transport_dib_ = MapTransportDIB(dib_id); 151 return transport_dib_; 152 } 153 154 int MockRenderProcessHost::GetID() const { 155 return id_; 156 } 157 158 bool MockRenderProcessHost::HasConnection() const { 159 return true; 160 } 161 162 void MockRenderProcessHost::SetIgnoreInputEvents(bool ignore_input_events) { 163 } 164 165 bool MockRenderProcessHost::IgnoreInputEvents() const { 166 return false; 167 } 168 169 void MockRenderProcessHost::Cleanup() { 170 if (listeners_.IsEmpty()) { 171 NotificationService::current()->Notify( 172 NOTIFICATION_RENDERER_PROCESS_TERMINATED, 173 Source<RenderProcessHost>(this), 174 NotificationService::NoDetails()); 175 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 176 RenderProcessHostImpl::UnregisterHost(GetID()); 177 } 178 } 179 180 void MockRenderProcessHost::AddPendingView() { 181 } 182 183 void MockRenderProcessHost::RemovePendingView() { 184 } 185 186 void MockRenderProcessHost::SetSuddenTerminationAllowed(bool allowed) { 187 } 188 189 bool MockRenderProcessHost::SuddenTerminationAllowed() const { 190 return true; 191 } 192 193 BrowserContext* MockRenderProcessHost::GetBrowserContext() const { 194 return browser_context_; 195 } 196 197 bool MockRenderProcessHost::InSameStoragePartition( 198 StoragePartition* partition) const { 199 // Mock RPHs only have one partition. 200 return true; 201 } 202 203 IPC::ChannelProxy* MockRenderProcessHost::GetChannel() { 204 return NULL; 205 } 206 207 int MockRenderProcessHost::GetActiveViewCount() { 208 int num_active_views = 0; 209 RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts(); 210 for (size_t i = 0; i < widgets.size(); ++i) { 211 // Count only RenderWidgetHosts in this process. 212 if (widgets[i]->GetProcess()->GetID() == GetID()) 213 num_active_views++; 214 } 215 return num_active_views; 216 } 217 218 bool MockRenderProcessHost::FastShutdownForPageCount(size_t count) { 219 if (static_cast<size_t>(GetActiveViewCount()) == count) 220 return FastShutdownIfPossible(); 221 return false; 222 } 223 224 base::TimeDelta MockRenderProcessHost::GetChildProcessIdleTime() const { 225 return base::TimeDelta::FromMilliseconds(0); 226 } 227 228 void MockRenderProcessHost::SurfaceUpdated(int32 surface_id) { 229 } 230 231 void MockRenderProcessHost::ResumeRequestsForView(int route_id) { 232 } 233 234 235 bool MockRenderProcessHost::OnMessageReceived(const IPC::Message& msg) { 236 IPC::Listener* listener = listeners_.Lookup(msg.routing_id()); 237 if (listener) 238 return listener->OnMessageReceived(msg); 239 return false; 240 } 241 242 void MockRenderProcessHost::OnChannelConnected(int32 peer_pid) { 243 } 244 245 MockRenderProcessHostFactory::MockRenderProcessHostFactory() {} 246 247 MockRenderProcessHostFactory::~MockRenderProcessHostFactory() { 248 // Detach this object from MockRenderProcesses to prevent STLDeleteElements() 249 // from calling MockRenderProcessHostFactory::Remove(). 250 for (ScopedVector<MockRenderProcessHost>::iterator it = processes_.begin(); 251 it != processes_.end(); ++it) { 252 (*it)->SetFactory(NULL); 253 } 254 } 255 256 RenderProcessHost* MockRenderProcessHostFactory::CreateRenderProcessHost( 257 BrowserContext* browser_context, 258 SiteInstance* site_instance) const { 259 MockRenderProcessHost* host = new MockRenderProcessHost(browser_context); 260 if (host) { 261 processes_.push_back(host); 262 host->SetFactory(this); 263 } 264 return host; 265 } 266 267 void MockRenderProcessHostFactory::Remove(MockRenderProcessHost* host) const { 268 for (ScopedVector<MockRenderProcessHost>::iterator it = processes_.begin(); 269 it != processes_.end(); ++it) { 270 if (*it == host) { 271 processes_.weak_erase(it); 272 break; 273 } 274 } 275 } 276 277 } // content 278