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