OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/proxy/ppapi_proxy_test.h" | 5 #include "ppapi/proxy/ppapi_proxy_test.h" |
6 | 6 |
| 7 #include "base/message_loop_proxy.h" |
| 8 #include "base/observer_list.h" |
| 9 #include "ipc/ipc_sync_channel.h" |
7 #include "ppapi/c/pp_errors.h" | 10 #include "ppapi/c/pp_errors.h" |
| 11 #include "ppapi/c/private/ppb_proxy_private.h" |
8 #include "ppapi/proxy/ppapi_messages.h" | 12 #include "ppapi/proxy/ppapi_messages.h" |
| 13 #include "ppapi/shared_impl/ppapi_preferences.cc" |
9 | 14 |
10 namespace pp { | 15 namespace pp { |
11 namespace proxy { | 16 namespace proxy { |
12 | 17 |
13 namespace { | 18 namespace { |
| 19 // HostDispatcher requires a PPB_Proxy_Private, so we always provide a fallback |
| 20 // do-nothing implementation. |
| 21 void PluginCrashed(PP_Module module) { |
| 22 NOTREACHED(); |
| 23 }; |
14 | 24 |
15 ProxyTestBase* current_test = NULL; | 25 PP_Instance GetInstanceForResource(PP_Resource resource) { |
| 26 // If a test relies on this, we need to implement it. |
| 27 NOTREACHED(); |
| 28 return 0; |
| 29 } |
| 30 |
| 31 void SetReserveInstanceIDCallback(PP_Module module, |
| 32 PP_Bool (*is_seen)(PP_Module, PP_Instance)) { |
| 33 // This function gets called in HostDispatcher's constructor. We simply don't |
| 34 // worry about Instance uniqueness in tests, so we can ignore the call. |
| 35 } |
| 36 |
| 37 int32_t GetURLLoaderBufferedBytes(PP_Resource url_loader) { |
| 38 NOTREACHED(); |
| 39 return 0; |
| 40 } |
| 41 |
| 42 void AddRefModule(PP_Module module) {} |
| 43 void ReleaseModule(PP_Module module) {} |
| 44 |
| 45 PPB_Proxy_Private ppb_proxy_private = { PluginCrashed, |
| 46 GetInstanceForResource, |
| 47 SetReserveInstanceIDCallback, |
| 48 GetURLLoaderBufferedBytes, |
| 49 AddRefModule, |
| 50 ReleaseModule }; |
| 51 |
| 52 // We allow multiple harnesses at a time to respond to 'GetInterface' calls. |
| 53 // We assume that only 1 harness's GetInterface function will ever support a |
| 54 // given interface name. In practice, there will either be only 1 GetInterface |
| 55 // handler (for PluginProxyTest or HostProxyTest), or there will be only 2 |
| 56 // GetInterface handlers (for TwoWayTest). In the latter case, one handler is |
| 57 // for the PluginProxyTestHarness and should only respond for PPP interfaces, |
| 58 // and the other handler is for the HostProxyTestHarness which should only |
| 59 // ever respond for PPB interfaces. |
| 60 ObserverList<ProxyTestHarnessBase> get_interface_handlers_; |
16 | 61 |
17 const void* MockGetInterface(const char* name) { | 62 const void* MockGetInterface(const char* name) { |
18 if (!current_test) { | 63 ObserverList<ProxyTestHarnessBase>::Iterator it = |
19 NOTREACHED(); | 64 get_interface_handlers_; |
20 return NULL; | 65 while (ProxyTestHarnessBase* observer = it.GetNext()) { |
| 66 const void* interface = observer->GetInterface(name); |
| 67 if (interface) |
| 68 return interface; |
21 } | 69 } |
22 return current_test->GetInterface(name); | 70 if (strcmp(name, PPB_PROXY_PRIVATE_INTERFACE) == 0) |
| 71 return &ppb_proxy_private; |
| 72 return NULL; |
| 73 } |
| 74 |
| 75 void SetUpRemoteHarness(ProxyTestHarnessBase* harness, |
| 76 const IPC::ChannelHandle& handle, |
| 77 base::MessageLoopProxy* ipc_message_loop_proxy, |
| 78 base::WaitableEvent* shutdown_event, |
| 79 base::WaitableEvent* harness_set_up) { |
| 80 harness->SetUpHarnessWithChannel(handle, ipc_message_loop_proxy, |
| 81 shutdown_event, false); |
| 82 harness_set_up->Signal(); |
| 83 } |
| 84 |
| 85 void TearDownRemoteHarness(ProxyTestHarnessBase* harness, |
| 86 base::WaitableEvent* harness_torn_down) { |
| 87 harness->TearDownHarness(); |
| 88 harness_torn_down->Signal(); |
23 } | 89 } |
24 | 90 |
25 } // namespace | 91 } // namespace |
26 | 92 |
27 // ProxyTestBase --------------------------------------------------------------- | 93 // ProxyTestHarnessBase -------------------------------------------------------- |
28 | 94 |
29 ProxyTestBase::ProxyTestBase() : pp_module_(0x98765), pp_instance_(0x12345) { | 95 ProxyTestHarnessBase::ProxyTestHarnessBase() : pp_module_(0x98765), |
30 DCHECK(!current_test); | 96 pp_instance_(0x12345) { |
31 current_test = this; | 97 get_interface_handlers_.AddObserver(this); |
32 } | 98 } |
33 | 99 |
34 ProxyTestBase::~ProxyTestBase() { | 100 ProxyTestHarnessBase::~ProxyTestHarnessBase() { |
35 DCHECK(current_test == this); | 101 get_interface_handlers_.RemoveObserver(this); |
36 current_test = NULL; | |
37 } | 102 } |
38 | 103 |
39 const void* ProxyTestBase::GetInterface(const char* name) { | 104 const void* ProxyTestHarnessBase::GetInterface(const char* name) { |
40 return registered_interfaces_[name]; | 105 return registered_interfaces_[name]; |
41 } | 106 } |
42 | 107 |
43 void ProxyTestBase::RegisterTestInterface(const char* name, | 108 void ProxyTestHarnessBase::RegisterTestInterface(const char* name, |
44 const void* interface) { | 109 const void* interface) { |
45 registered_interfaces_[name] = interface; | 110 registered_interfaces_[name] = interface; |
46 } | 111 } |
47 | 112 |
48 bool ProxyTestBase::SupportsInterface(const char* name) { | 113 bool ProxyTestHarnessBase::SupportsInterface(const char* name) { |
49 sink().ClearMessages(); | 114 sink().ClearMessages(); |
50 | 115 |
51 // IPC doesn't actually write to this when we send a message manually | 116 // IPC doesn't actually write to this when we send a message manually |
52 // not actually using IPC. | 117 // not actually using IPC. |
53 bool unused_result = false; | 118 bool unused_result = false; |
54 PpapiMsg_SupportsInterface msg(name, &unused_result); | 119 PpapiMsg_SupportsInterface msg(name, &unused_result); |
55 GetDispatcher()->OnMessageReceived(msg); | 120 GetDispatcher()->OnMessageReceived(msg); |
56 | 121 |
57 const IPC::Message* reply_msg = | 122 const IPC::Message* reply_msg = |
58 sink().GetUniqueMessageMatching(IPC_REPLY_ID); | 123 sink().GetUniqueMessageMatching(IPC_REPLY_ID); |
59 EXPECT_TRUE(reply_msg); | 124 EXPECT_TRUE(reply_msg); |
60 if (!reply_msg) | 125 if (!reply_msg) |
61 return false; | 126 return false; |
62 | 127 |
63 TupleTypes<PpapiMsg_SupportsInterface::ReplyParam>::ValueTuple reply_data; | 128 TupleTypes<PpapiMsg_SupportsInterface::ReplyParam>::ValueTuple reply_data; |
64 EXPECT_TRUE(PpapiMsg_SupportsInterface::ReadReplyParam( | 129 EXPECT_TRUE(PpapiMsg_SupportsInterface::ReadReplyParam( |
65 reply_msg, &reply_data)); | 130 reply_msg, &reply_data)); |
66 | 131 |
67 sink().ClearMessages(); | 132 sink().ClearMessages(); |
68 return reply_data.a; | 133 return reply_data.a; |
69 } | 134 } |
70 | 135 |
71 // PluginProxyTest ------------------------------------------------------------- | 136 // PluginProxyTestHarness ------------------------------------------------------ |
72 | 137 |
73 PluginProxyTest::PluginProxyTest() { | 138 PluginProxyTestHarness::PluginProxyTestHarness() { |
74 } | 139 } |
75 | 140 |
76 PluginProxyTest::~PluginProxyTest() { | 141 PluginProxyTestHarness::~PluginProxyTestHarness() { |
77 } | 142 } |
78 | 143 |
79 Dispatcher* PluginProxyTest::GetDispatcher() { | 144 Dispatcher* PluginProxyTestHarness::GetDispatcher() { |
80 return plugin_dispatcher_.get(); | 145 return plugin_dispatcher_.get(); |
81 } | 146 } |
82 | 147 |
83 void PluginProxyTest::SetUp() { | 148 void PluginProxyTestHarness::SetUpHarness() { |
84 // These must be first since the dispatcher set-up uses them. | 149 // These must be first since the dispatcher set-up uses them. |
85 PluginResourceTracker::SetInstanceForTest(&resource_tracker_); | 150 PluginResourceTracker::SetInstanceForTest(&resource_tracker_); |
86 PluginVarTracker::SetInstanceForTest(&var_tracker_); | 151 PluginVarTracker::SetInstanceForTest(&var_tracker_); |
87 | 152 |
88 plugin_dispatcher_.reset(new PluginDispatcher( | 153 plugin_dispatcher_.reset(new PluginDispatcher( |
89 base::Process::Current().handle(), | 154 base::Process::Current().handle(), |
90 &MockGetInterface)); | 155 &MockGetInterface)); |
91 plugin_dispatcher_->InitWithTestSink(&sink()); | 156 plugin_dispatcher_->InitWithTestSink(&sink()); |
92 plugin_dispatcher_->DidCreateInstance(pp_instance()); | 157 plugin_dispatcher_->DidCreateInstance(pp_instance()); |
93 } | 158 } |
94 | 159 |
95 void PluginProxyTest::TearDown() { | 160 void PluginProxyTestHarness::SetUpHarnessWithChannel( |
| 161 const IPC::ChannelHandle& channel_handle, |
| 162 base::MessageLoopProxy* ipc_message_loop, |
| 163 base::WaitableEvent* shutdown_event, |
| 164 bool is_client) { |
| 165 // These must be first since the dispatcher set-up uses them. |
| 166 PluginResourceTracker::SetInstanceForTest(&resource_tracker_); |
| 167 PluginVarTracker::SetInstanceForTest(&var_tracker_); |
| 168 plugin_delegate_mock_.Init(ipc_message_loop, shutdown_event); |
| 169 |
| 170 plugin_dispatcher_.reset(new PluginDispatcher( |
| 171 base::Process::Current().handle(), |
| 172 &MockGetInterface)); |
| 173 plugin_dispatcher_->InitPluginWithChannel(&plugin_delegate_mock_, |
| 174 channel_handle, |
| 175 is_client); |
| 176 plugin_dispatcher_->DidCreateInstance(pp_instance()); |
| 177 } |
| 178 |
| 179 void PluginProxyTestHarness::TearDownHarness() { |
96 plugin_dispatcher_->DidDestroyInstance(pp_instance()); | 180 plugin_dispatcher_->DidDestroyInstance(pp_instance()); |
97 plugin_dispatcher_.reset(); | 181 plugin_dispatcher_.reset(); |
98 | 182 |
99 PluginVarTracker::SetInstanceForTest(NULL); | 183 PluginVarTracker::SetInstanceForTest(NULL); |
100 PluginResourceTracker::SetInstanceForTest(NULL); | 184 PluginResourceTracker::SetInstanceForTest(NULL); |
101 } | 185 } |
102 | 186 |
103 // HostProxyTest --------------------------------------------------------------- | 187 base::MessageLoopProxy* |
104 | 188 PluginProxyTestHarness::PluginDelegateMock::GetIPCMessageLoop() { |
105 HostProxyTest::HostProxyTest() { | 189 return ipc_message_loop_; |
106 } | 190 } |
107 | 191 |
108 HostProxyTest::~HostProxyTest() { | 192 base::WaitableEvent* |
| 193 PluginProxyTestHarness::PluginDelegateMock::GetShutdownEvent() { |
| 194 return shutdown_event_; |
109 } | 195 } |
110 | 196 |
111 Dispatcher* HostProxyTest::GetDispatcher() { | 197 std::set<PP_Instance>* |
| 198 PluginProxyTestHarness::PluginDelegateMock::GetGloballySeenInstanceIDSet() { |
| 199 return &instance_id_set_; |
| 200 } |
| 201 |
| 202 ppapi::WebKitForwarding* |
| 203 PluginProxyTestHarness::PluginDelegateMock::GetWebKitForwarding() { |
| 204 NOTREACHED(); |
| 205 return NULL; |
| 206 } |
| 207 |
| 208 void PluginProxyTestHarness::PluginDelegateMock::PostToWebKitThread( |
| 209 const tracked_objects::Location& from_here, const base::Closure& task) { |
| 210 NOTREACHED(); |
| 211 } |
| 212 |
| 213 bool PluginProxyTestHarness::PluginDelegateMock::SendToBrowser( |
| 214 IPC::Message* msg) { |
| 215 NOTREACHED(); |
| 216 return false; |
| 217 } |
| 218 |
| 219 |
| 220 // PluginProxyTest ------------------------------------------------------------- |
| 221 |
| 222 PluginProxyTest::PluginProxyTest() { |
| 223 } |
| 224 |
| 225 PluginProxyTest::~PluginProxyTest() { |
| 226 } |
| 227 |
| 228 void PluginProxyTest::SetUp() { |
| 229 SetUpHarness(); |
| 230 } |
| 231 |
| 232 void PluginProxyTest::TearDown() { |
| 233 TearDownHarness(); |
| 234 } |
| 235 |
| 236 // HostProxyTestHarness -------------------------------------------------------- |
| 237 |
| 238 HostProxyTestHarness::HostProxyTestHarness() { |
| 239 } |
| 240 |
| 241 HostProxyTestHarness::~HostProxyTestHarness() { |
| 242 } |
| 243 |
| 244 Dispatcher* HostProxyTestHarness::GetDispatcher() { |
112 return host_dispatcher_.get(); | 245 return host_dispatcher_.get(); |
113 } | 246 } |
114 | 247 |
115 void HostProxyTest::SetUp() { | 248 void HostProxyTestHarness::SetUpHarness() { |
116 host_dispatcher_.reset(new HostDispatcher( | 249 host_dispatcher_.reset(new HostDispatcher( |
117 base::Process::Current().handle(), | 250 base::Process::Current().handle(), |
118 pp_module(), | 251 pp_module(), |
119 &MockGetInterface)); | 252 &MockGetInterface)); |
120 host_dispatcher_->InitWithTestSink(&sink()); | 253 host_dispatcher_->InitWithTestSink(&sink()); |
121 HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get()); | 254 HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get()); |
122 } | 255 } |
123 | 256 |
124 void HostProxyTest::TearDown() { | 257 void HostProxyTestHarness::SetUpHarnessWithChannel( |
| 258 const IPC::ChannelHandle& channel_handle, |
| 259 base::MessageLoopProxy* ipc_message_loop, |
| 260 base::WaitableEvent* shutdown_event, |
| 261 bool is_client) { |
| 262 delegate_mock_.Init(ipc_message_loop, shutdown_event); |
| 263 host_dispatcher_.reset(new HostDispatcher( |
| 264 base::Process::Current().handle(), |
| 265 pp_module(), |
| 266 &MockGetInterface)); |
| 267 ppapi::Preferences preferences; |
| 268 host_dispatcher_->InitHostWithChannel(&delegate_mock_, channel_handle, |
| 269 is_client, preferences); |
| 270 HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get()); |
| 271 } |
| 272 |
| 273 void HostProxyTestHarness::TearDownHarness() { |
125 HostDispatcher::RemoveForInstance(pp_instance()); | 274 HostDispatcher::RemoveForInstance(pp_instance()); |
126 host_dispatcher_.reset(); | 275 host_dispatcher_.reset(); |
127 } | 276 } |
128 | 277 |
| 278 base::MessageLoopProxy* |
| 279 HostProxyTestHarness::DelegateMock::GetIPCMessageLoop() { |
| 280 return ipc_message_loop_; |
| 281 } |
| 282 |
| 283 base::WaitableEvent* HostProxyTestHarness::DelegateMock::GetShutdownEvent() { |
| 284 return shutdown_event_; |
| 285 } |
| 286 |
| 287 |
| 288 // HostProxyTest --------------------------------------------------------------- |
| 289 |
| 290 HostProxyTest::HostProxyTest() { |
| 291 } |
| 292 |
| 293 HostProxyTest::~HostProxyTest() { |
| 294 } |
| 295 |
| 296 void HostProxyTest::SetUp() { |
| 297 SetUpHarness(); |
| 298 } |
| 299 |
| 300 void HostProxyTest::TearDown() { |
| 301 TearDownHarness(); |
| 302 } |
| 303 |
| 304 // TwoWayTest --------------------------------------------------------------- |
| 305 |
| 306 TwoWayTest::TwoWayTest(TwoWayTest::TwoWayTestMode test_mode) |
| 307 : test_mode_(test_mode), |
| 308 io_thread_("TwoWayTest_IOThread"), |
| 309 plugin_thread_("TwoWayTest_PluginThread"), |
| 310 remote_harness_(NULL), |
| 311 local_harness_(NULL), |
| 312 channel_created_(true, false), |
| 313 shutdown_event_(true, false) { |
| 314 if (test_mode == TEST_PPP_INTERFACE) { |
| 315 remote_harness_ = &plugin_; |
| 316 local_harness_ = &host_; |
| 317 } else { |
| 318 remote_harness_ = &host_; |
| 319 local_harness_ = &plugin_; |
| 320 } |
| 321 } |
| 322 |
| 323 TwoWayTest::~TwoWayTest() { |
| 324 shutdown_event_.Signal(); |
| 325 } |
| 326 |
| 327 void TwoWayTest::SetUp() { |
| 328 base::Thread::Options options; |
| 329 options.message_loop_type = MessageLoop::TYPE_IO; |
| 330 io_thread_.StartWithOptions(options); |
| 331 plugin_thread_.Start(); |
| 332 |
| 333 IPC::ChannelHandle handle; |
| 334 handle.name = "TwoWayTestChannel"; |
| 335 |
| 336 base::WaitableEvent remote_harness_set_up(true, false); |
| 337 plugin_thread_.message_loop_proxy()->PostTask( |
| 338 FROM_HERE, |
| 339 NewRunnableFunction(&SetUpRemoteHarness, |
| 340 remote_harness_, |
| 341 handle, |
| 342 io_thread_.message_loop_proxy(), |
| 343 &shutdown_event_, |
| 344 &remote_harness_set_up)); |
| 345 remote_harness_set_up.Wait(); |
| 346 local_harness_->SetUpHarnessWithChannel(handle, |
| 347 io_thread_.message_loop_proxy(), |
| 348 &shutdown_event_, |
| 349 true); // is_client |
| 350 } |
| 351 |
| 352 void TwoWayTest::TearDown() { |
| 353 base::WaitableEvent remote_harness_torn_down(true, false); |
| 354 plugin_thread_.message_loop_proxy()->PostTask( |
| 355 FROM_HERE, |
| 356 NewRunnableFunction(&TearDownRemoteHarness, |
| 357 remote_harness_, |
| 358 &remote_harness_torn_down)); |
| 359 remote_harness_torn_down.Wait(); |
| 360 |
| 361 local_harness_->TearDownHarness(); |
| 362 |
| 363 io_thread_.Stop(); |
| 364 } |
| 365 |
| 366 |
129 } // namespace proxy | 367 } // namespace proxy |
130 } // namespace pp | 368 } // namespace pp |
OLD | NEW |