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_thread.h" 6 7 #include "base/message_loop/message_loop_proxy.h" 8 #include "content/common/view_messages.h" 9 #include "content/public/renderer/render_process_observer.h" 10 #include "ipc/ipc_message_utils.h" 11 #include "ipc/ipc_sync_message.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "third_party/WebKit/public/web/WebScriptController.h" 14 15 namespace content { 16 17 MockRenderThread::MockRenderThread() 18 : routing_id_(0), 19 surface_id_(0), 20 opener_id_(0), 21 new_window_routing_id_(0), 22 new_window_main_frame_routing_id_(0) { 23 } 24 25 MockRenderThread::~MockRenderThread() { 26 } 27 28 void MockRenderThread::VerifyRunJavaScriptMessageSend( 29 const base::string16& expected_alert_message) { 30 const IPC::Message* alert_msg = 31 sink_.GetUniqueMessageMatching(ViewHostMsg_RunJavaScriptMessage::ID); 32 ASSERT_TRUE(alert_msg); 33 PickleIterator iter = IPC::SyncMessage::GetDataIterator(alert_msg); 34 ViewHostMsg_RunJavaScriptMessage::SendParam alert_param; 35 ASSERT_TRUE(IPC::ReadParam(alert_msg, &iter, &alert_param)); 36 EXPECT_EQ(expected_alert_message, alert_param.a); 37 } 38 39 // Called by the Widget. Used to send messages to the browser. 40 // We short-circuit the mechanism and handle the messages right here on this 41 // class. 42 bool MockRenderThread::Send(IPC::Message* msg) { 43 // We need to simulate a synchronous channel, thus we are going to receive 44 // through this function messages, messages with reply and reply messages. 45 // We can only handle one synchronous message at a time. 46 if (msg->is_reply()) { 47 if (reply_deserializer_) { 48 reply_deserializer_->SerializeOutputParameters(*msg); 49 reply_deserializer_.reset(); 50 } 51 } else { 52 if (msg->is_sync()) { 53 // We actually need to handle deleting the reply deserializer for sync 54 // messages. 55 reply_deserializer_.reset( 56 static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer()); 57 } 58 if (msg->routing_id() == MSG_ROUTING_CONTROL) 59 OnControlMessageReceived(*msg); 60 else 61 OnMessageReceived(*msg); 62 } 63 delete msg; 64 return true; 65 } 66 67 base::MessageLoop* MockRenderThread::GetMessageLoop() { 68 return NULL; 69 } 70 71 IPC::SyncChannel* MockRenderThread::GetChannel() { 72 return NULL; 73 } 74 75 std::string MockRenderThread::GetLocale() { 76 return "en-US"; 77 } 78 79 IPC::SyncMessageFilter* MockRenderThread::GetSyncMessageFilter() { 80 return NULL; 81 } 82 83 scoped_refptr<base::MessageLoopProxy> 84 MockRenderThread::GetIOMessageLoopProxy() { 85 return scoped_refptr<base::MessageLoopProxy>(); 86 } 87 88 void MockRenderThread::AddRoute(int32 routing_id, IPC::Listener* listener) { 89 // We may hear this for views created from OnCreateWindow as well, 90 // in which case we don't want to track the new widget. 91 if (routing_id_ == routing_id) 92 widget_ = listener; 93 } 94 95 void MockRenderThread::RemoveRoute(int32 routing_id) { 96 // We may hear this for views created from OnCreateWindow as well, 97 // in which case we don't want to track the new widget. 98 if (routing_id_ == routing_id) 99 widget_ = NULL; 100 } 101 102 int MockRenderThread::GenerateRoutingID() { 103 NOTREACHED(); 104 return MSG_ROUTING_NONE; 105 } 106 107 void MockRenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { 108 filter->OnFilterAdded(&sink()); 109 // Add this filter to a vector so the MockRenderThread::RemoveFilter function 110 // can check if this filter is added. 111 filters_.push_back(make_scoped_refptr(filter)); 112 } 113 114 void MockRenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { 115 // Emulate the IPC::ChannelProxy::OnRemoveFilter function. 116 for (size_t i = 0; i < filters_.size(); ++i) { 117 if (filters_[i].get() == filter) { 118 filter->OnFilterRemoved(); 119 filters_.erase(filters_.begin() + i); 120 return; 121 } 122 } 123 NOTREACHED() << "filter to be removed not found"; 124 } 125 126 void MockRenderThread::AddObserver(RenderProcessObserver* observer) { 127 observers_.AddObserver(observer); 128 } 129 130 void MockRenderThread::RemoveObserver(RenderProcessObserver* observer) { 131 observers_.RemoveObserver(observer); 132 } 133 134 void MockRenderThread::SetResourceDispatcherDelegate( 135 ResourceDispatcherDelegate* delegate) { 136 } 137 138 void MockRenderThread::WidgetHidden() { 139 } 140 141 void MockRenderThread::WidgetRestored() { 142 } 143 144 void MockRenderThread::EnsureWebKitInitialized() { 145 } 146 147 void MockRenderThread::RecordAction(const UserMetricsAction& action) { 148 } 149 150 void MockRenderThread::RecordComputedAction(const std::string& action) { 151 } 152 153 scoped_ptr<base::SharedMemory> 154 MockRenderThread::HostAllocateSharedMemoryBuffer( 155 size_t buffer_size) { 156 scoped_ptr<base::SharedMemory> shared_buf(new base::SharedMemory); 157 if (!shared_buf->CreateAndMapAnonymous(buffer_size)) { 158 NOTREACHED() << "Cannot map shared memory buffer"; 159 return scoped_ptr<base::SharedMemory>(); 160 } 161 162 return scoped_ptr<base::SharedMemory>(shared_buf.release()); 163 } 164 165 void MockRenderThread::RegisterExtension(v8::Extension* extension) { 166 blink::WebScriptController::registerExtension(extension); 167 } 168 169 void MockRenderThread::ScheduleIdleHandler(int64 initial_delay_ms) { 170 } 171 172 void MockRenderThread::IdleHandler() { 173 } 174 175 int64 MockRenderThread::GetIdleNotificationDelayInMs() const { 176 return 0; 177 } 178 179 void MockRenderThread::SetIdleNotificationDelayInMs( 180 int64 idle_notification_delay_in_ms) { 181 } 182 183 void MockRenderThread::ToggleWebKitSharedTimer(bool suspend) { 184 } 185 186 void MockRenderThread::UpdateHistograms(int sequence_number) { 187 } 188 189 int MockRenderThread::PostTaskToAllWebWorkers(const base::Closure& closure) { 190 return 0; 191 } 192 193 bool MockRenderThread::ResolveProxy(const GURL& url, std::string* proxy_list) { 194 return false; 195 } 196 197 #if defined(OS_WIN) 198 void MockRenderThread::PreCacheFont(const LOGFONT& log_font) { 199 } 200 201 void MockRenderThread::ReleaseCachedFonts() { 202 } 203 204 #endif // OS_WIN 205 206 void MockRenderThread::SendCloseMessage() { 207 ViewMsg_Close msg(routing_id_); 208 widget_->OnMessageReceived(msg); 209 } 210 211 // The Widget expects to be returned valid route_id. 212 void MockRenderThread::OnCreateWidget(int opener_id, 213 blink::WebPopupType popup_type, 214 int* route_id, 215 int* surface_id) { 216 opener_id_ = opener_id; 217 *route_id = routing_id_; 218 *surface_id = surface_id_; 219 } 220 221 // The View expects to be returned a valid route_id different from its own. 222 void MockRenderThread::OnCreateWindow( 223 const ViewHostMsg_CreateWindow_Params& params, 224 int* route_id, 225 int* main_frame_route_id, 226 int* surface_id, 227 int64* cloned_session_storage_namespace_id) { 228 *route_id = new_window_routing_id_; 229 *main_frame_route_id = new_window_main_frame_routing_id_; 230 *surface_id = surface_id_; 231 *cloned_session_storage_namespace_id = 0; 232 } 233 234 bool MockRenderThread::OnControlMessageReceived(const IPC::Message& msg) { 235 ObserverListBase<RenderProcessObserver>::Iterator it(observers_); 236 RenderProcessObserver* observer; 237 while ((observer = it.GetNext()) != NULL) { 238 if (observer->OnControlMessageReceived(msg)) 239 return true; 240 } 241 return OnMessageReceived(msg); 242 } 243 244 bool MockRenderThread::OnMessageReceived(const IPC::Message& msg) { 245 // Save the message in the sink. 246 sink_.OnMessageReceived(msg); 247 248 bool handled = true; 249 bool msg_is_ok = true; 250 IPC_BEGIN_MESSAGE_MAP_EX(MockRenderThread, msg, msg_is_ok) 251 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget) 252 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnCreateWindow) 253 IPC_MESSAGE_UNHANDLED(handled = false) 254 IPC_END_MESSAGE_MAP_EX() 255 return handled; 256 } 257 258 #if defined(OS_WIN) 259 void MockRenderThread::OnDuplicateSection( 260 base::SharedMemoryHandle renderer_handle, 261 base::SharedMemoryHandle* browser_handle) { 262 // We don't have to duplicate the input handles since RenderViewTest does not 263 // separate a browser process from a renderer process. 264 *browser_handle = renderer_handle; 265 } 266 #endif // defined(OS_WIN) 267 268 } // namespace content 269