[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 1 | // Copyright (c) 2010 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 <string> |
| 6 | #include "base/file_path.h" |
| 7 | #include "base/waitable_event.h" |
[email protected] | a8ba636 | 2010-11-10 20:02:25 | [diff] [blame^] | 8 | #include "chrome/common/automation_messages.h" |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 9 | #include "chrome_frame/cfproxy_private.h" |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 10 | #include "testing/gtest/include/gtest/gtest.h" |
| 11 | #include "testing/gmock/include/gmock/gmock.h" |
| 12 | #include "testing/gmock_mutant.h" |
| 13 | |
| 14 | using testing::_; |
| 15 | using testing::DoAll; |
| 16 | using testing::NotNull; |
| 17 | using testing::Return; |
| 18 | using testing::StrictMock; |
| 19 | using testing::InvokeWithoutArgs; |
| 20 | using testing::WithoutArgs; |
| 21 | using testing::CreateFunctor; |
[email protected] | ccdf73e | 2010-10-07 20:15:19 | [diff] [blame] | 22 | using testing::StrEq; |
| 23 | using testing::Eq; |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 24 | |
| 25 | // There is not much to test here since CFProxy is pretty dumb. |
| 26 | struct MockFactory : public ChromeProxyFactory { |
| 27 | MOCK_METHOD0(CreateProxy, ChromeProxy*()); |
| 28 | }; |
| 29 | |
| 30 | struct MockChromeProxyDelegate : public ChromeProxyDelegate { |
| 31 | MOCK_METHOD1(Connected, void(ChromeProxy* proxy)); |
| 32 | MOCK_METHOD2(PeerLost, void(ChromeProxy*, enum DisconnectReason reason)); |
| 33 | MOCK_METHOD0(Disconnected, void()); |
| 34 | MOCK_METHOD0(tab_handle, int()); |
| 35 | |
[email protected] | 751bf4b | 2010-11-05 22:06:31 | [diff] [blame] | 36 | MOCK_METHOD5(Completed_CreateTab, void(bool success, HWND chrome_wnd, |
| 37 | HWND tab_window, int tab_handle, int session_id)); |
| 38 | MOCK_METHOD5(Completed_ConnectToTab, void(bool success, HWND chrome_window, |
| 39 | HWND tab_window, int tab_handle, int session_id)); |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 40 | MOCK_METHOD2(Completed_Navigate, void(bool success, |
| 41 | enum AutomationMsg_NavigationResponseValues res)); |
| 42 | MOCK_METHOD3(Completed_InstallExtension, void(bool success, |
| 43 | enum AutomationMsg_ExtensionResponseValues res, SyncMessageContext* ctx)); |
| 44 | MOCK_METHOD3(Completed_LoadExpandedExtension, void(bool success, |
| 45 | enum AutomationMsg_ExtensionResponseValues res, SyncMessageContext* ctx)); |
| 46 | MOCK_METHOD2(Completed_GetEnabledExtensions, void(bool success, |
| 47 | const std::vector<FilePath>* v)); |
| 48 | |
| 49 | // Network requests from Chrome. |
| 50 | MOCK_METHOD2(Network_Start, void(int request_id, |
| 51 | const IPC::AutomationURLRequest& request_info)); |
| 52 | MOCK_METHOD2(Network_Read, void(int request_id, int bytes_to_read)); |
| 53 | MOCK_METHOD2(Network_End, void(int request_id, const URLRequestStatus& s)); |
| 54 | MOCK_METHOD1(Network_DownloadInHost, void(int request_id)); |
| 55 | MOCK_METHOD2(GetCookies, void(const GURL& url, int cookie_id)); |
| 56 | MOCK_METHOD2(SetCookie, void(const GURL& url, const std::string& cookie)); |
| 57 | |
| 58 | // Navigation progress notifications. |
| 59 | MOCK_METHOD2(NavigationStateChanged, void(int flags, |
| 60 | const IPC::NavigationInfo& nav_info)); |
| 61 | MOCK_METHOD1(UpdateTargetUrl, void(const std::wstring& url)); |
| 62 | MOCK_METHOD2(NavigationFailed, void(int error_code, const GURL& gurl)); |
| 63 | MOCK_METHOD1(DidNavigate, void(const IPC::NavigationInfo& navigation_info)); |
| 64 | MOCK_METHOD1(TabLoaded, void(const GURL& url)); |
| 65 | |
| 66 | // |
| 67 | MOCK_METHOD3(OpenURL, void(const GURL& url_to_open, const GURL& referrer, |
| 68 | int open_disposition)); |
| 69 | MOCK_METHOD1(GoToHistoryOffset, void(int offset)); |
| 70 | MOCK_METHOD3(MessageToHost, void(const std::string& message, |
| 71 | const std::string& origin, const std::string& target)); |
| 72 | |
| 73 | // Misc. UI. |
| 74 | MOCK_METHOD1(HandleAccelerator, void(const MSG& accel_message)); |
[email protected] | ccdf73e | 2010-10-07 20:15:19 | [diff] [blame] | 75 | MOCK_METHOD3(HandleContextMenu, void(HANDLE menu_handle, int align_flags, |
[email protected] | 47af65f | 2010-11-08 21:43:55 | [diff] [blame] | 76 | const IPC::MiniContextMenuParams& params)); |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 77 | MOCK_METHOD1(TabbedOut, void(bool reverse)); |
| 78 | |
| 79 | // |
| 80 | MOCK_METHOD0(TabClosed, void()); |
| 81 | MOCK_METHOD1(AttachTab, |
| 82 | void(const IPC::AttachExternalTabParams& attach_params)); |
| 83 | }; |
| 84 | |
| 85 | struct MockSender : public IPC::Message::Sender { |
| 86 | MOCK_METHOD1(Send, bool(IPC::Message* m)); |
| 87 | }; |
| 88 | |
| 89 | struct MockCFProxyTraits : public CFProxyTraits { |
| 90 | MOCK_METHOD2(DoCreateChannel, IPC::Message::Sender*(const std::string& id, |
| 91 | IPC::Channel::Listener* l)); |
| 92 | MOCK_METHOD1(CloseChannel, void(IPC::Message::Sender* s)); |
| 93 | MOCK_METHOD1(LaunchApp, bool(const std::wstring& cmd_line)); |
| 94 | |
| 95 | // Forward the CreateChannel to DoCreateChannel, but save the ipc_thread |
| 96 | // and the listener (i.e. proxy implementation of Channel::Listener) |
| 97 | virtual IPC::Message::Sender* CreateChannel(const std::string& id, |
| 98 | IPC::Channel::Listener* l) { |
| 99 | ipc_loop = MessageLoop::current(); |
| 100 | listener = l; |
| 101 | return this->DoCreateChannel(id, l); |
| 102 | } |
| 103 | |
| 104 | // Simulate some activity in the IPC thread. |
| 105 | // You may find API_FIRE_XXXX macros (see below) handy instead. |
| 106 | void FireConnect(base::TimeDelta t) { |
| 107 | ASSERT_TRUE(ipc_loop != NULL); |
| 108 | ipc_loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(listener, |
| 109 | &IPC::Channel::Listener::OnChannelConnected, 0), t.InMilliseconds()); |
| 110 | } |
| 111 | |
| 112 | void FireError(base::TimeDelta t) { |
| 113 | ASSERT_TRUE(ipc_loop != NULL); |
| 114 | ipc_loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(listener, |
| 115 | &IPC::Channel::Listener::OnChannelError), t.InMilliseconds()); |
| 116 | } |
| 117 | |
| 118 | void FireMessage(const IPC::Message& m, base::TimeDelta t) { |
| 119 | ASSERT_TRUE(ipc_loop != NULL); |
| 120 | ipc_loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(listener, |
| 121 | &IPC::Channel::Listener::OnMessageReceived, m), t.InMilliseconds()); |
| 122 | } |
| 123 | |
| 124 | MockCFProxyTraits() : ipc_loop(NULL) {} |
| 125 | MockSender sender; |
| 126 | private: |
| 127 | MessageLoop* ipc_loop; |
| 128 | IPC::Channel::Listener* listener; |
| 129 | }; |
| 130 | |
| 131 | // Handy macros when we want so similate something on the IPC thread. |
| 132 | #define API_FIRE_CONNECT(api, t) InvokeWithoutArgs(CreateFunctor(&api, \ |
| 133 | &MockCFProxyTraits::FireConnect, t)) |
| 134 | #define API_FIRE_ERROR(api, t) InvokeWithoutArgs(CreateFunctor(&api, \ |
| 135 | &MockCFProxyTraits::FireError, t)) |
| 136 | #define API_FIRE_MESSAGE(api, t) InvokeWithoutArgs(CreateFunctor(&api, \ |
| 137 | &MockCFProxyTraits::FireMessage, t)) |
| 138 | DISABLE_RUNNABLE_METHOD_REFCOUNT(IPC::Channel::Listener); |
| 139 | |
| 140 | TEST(ChromeProxy, DelegateAddRemove) { |
| 141 | StrictMock<MockCFProxyTraits> api; |
| 142 | StrictMock<MockChromeProxyDelegate> delegate; |
| 143 | StrictMock<MockFactory> factory; // to be destroyed before other mocks |
| 144 | CFProxy* proxy = new CFProxy(&api); |
| 145 | |
| 146 | EXPECT_CALL(factory, CreateProxy()).WillOnce(Return(proxy)); |
| 147 | EXPECT_CALL(api, DoCreateChannel(_, proxy)).WillOnce(Return(&api.sender)); |
| 148 | EXPECT_CALL(api, LaunchApp(_)).WillOnce(Return(true)); |
| 149 | EXPECT_CALL(api, CloseChannel(&api.sender)); |
| 150 | |
| 151 | EXPECT_CALL(delegate, tab_handle()).WillRepeatedly(Return(0)); |
| 152 | EXPECT_CALL(delegate, Disconnected()); |
| 153 | |
| 154 | ProxyParams params; |
| 155 | params.profile = "Adam N. Epilinter"; |
| 156 | params.timeout = base::TimeDelta::FromSeconds(4); |
| 157 | factory.GetProxy(&delegate, params); |
| 158 | factory.ReleaseProxy(&delegate, params.profile); |
| 159 | } |
| 160 | |
| 161 | // Not very useful test. Just for illustration. :) |
| 162 | TEST(ChromeProxy, SharedProxy) { |
| 163 | base::WaitableEvent done1(false, false); |
| 164 | base::WaitableEvent done2(false, false); |
| 165 | StrictMock<MockCFProxyTraits> api; |
| 166 | StrictMock<MockChromeProxyDelegate> delegate1; |
| 167 | StrictMock<MockChromeProxyDelegate> delegate2; |
| 168 | StrictMock<MockFactory> factory; |
| 169 | CFProxy* proxy = new CFProxy(&api); |
| 170 | |
| 171 | EXPECT_CALL(factory, CreateProxy()).WillOnce(Return(proxy)); |
| 172 | EXPECT_CALL(api, DoCreateChannel(_, proxy)).WillOnce(Return(&api.sender)); |
| 173 | EXPECT_CALL(api, LaunchApp(_)).WillOnce(DoAll( |
| 174 | API_FIRE_CONNECT(api, base::TimeDelta::FromMilliseconds(150)), |
| 175 | Return(true))); |
| 176 | EXPECT_CALL(api, CloseChannel(&api.sender)); |
| 177 | |
| 178 | EXPECT_CALL(delegate1, tab_handle()).WillRepeatedly(Return(0)); |
| 179 | EXPECT_CALL(delegate2, tab_handle()).WillRepeatedly(Return(0)); |
| 180 | |
| 181 | EXPECT_CALL(delegate1, Connected(proxy)) |
| 182 | .WillOnce(InvokeWithoutArgs(&done1, &base::WaitableEvent::Signal)); |
| 183 | EXPECT_CALL(delegate2, Connected(proxy)) |
| 184 | .WillOnce(InvokeWithoutArgs(&done2, &base::WaitableEvent::Signal)); |
| 185 | |
| 186 | ProxyParams params; |
| 187 | params.profile = "Adam N. Epilinter"; |
| 188 | params.timeout = base::TimeDelta::FromSeconds(4); |
| 189 | |
| 190 | factory.GetProxy(&delegate1, params); |
| 191 | params.timeout = base::TimeDelta::FromSeconds(2); |
| 192 | factory.GetProxy(&delegate2, params); |
| 193 | |
| 194 | EXPECT_TRUE(done1.TimedWait(base::TimeDelta::FromSeconds(1))); |
| 195 | EXPECT_TRUE(done2.TimedWait(base::TimeDelta::FromSeconds(1))); |
| 196 | |
| 197 | EXPECT_CALL(delegate2, Disconnected()); |
| 198 | EXPECT_CALL(delegate1, Disconnected()); |
| 199 | |
| 200 | factory.ReleaseProxy(&delegate2, params.profile); |
| 201 | factory.ReleaseProxy(&delegate1, params.profile); |
| 202 | } |
| 203 | |
| 204 | TEST(ChromeProxy, LaunchTimeout) { |
| 205 | base::WaitableEvent done(true, false); |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 206 | StrictMock<MockCFProxyTraits> api; |
| 207 | StrictMock<MockChromeProxyDelegate> delegate; |
[email protected] | 68a6606 | 2010-10-06 18:11:26 | [diff] [blame] | 208 | StrictMock<MockFactory> factory; |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 209 | CFProxy* proxy = new CFProxy(&api); |
| 210 | |
| 211 | EXPECT_CALL(delegate, tab_handle()).WillRepeatedly(Return(0)); |
| 212 | EXPECT_CALL(factory, CreateProxy()).WillOnce(Return(proxy)); |
| 213 | EXPECT_CALL(api, DoCreateChannel(_, proxy)).WillOnce(Return(&api.sender)); |
| 214 | EXPECT_CALL(api, LaunchApp(_)).WillOnce(Return(true)); |
| 215 | EXPECT_CALL(api, CloseChannel(&api.sender)); |
| 216 | |
| 217 | EXPECT_CALL(delegate, PeerLost(_, |
| 218 | ChromeProxyDelegate::CHROME_EXE_LAUNCH_TIMEOUT)) |
| 219 | .WillOnce(InvokeWithoutArgs(&done, &base::WaitableEvent::Signal)); |
| 220 | ProxyParams params; |
| 221 | params.profile = "Adam N. Epilinter"; |
| 222 | params.timeout = base::TimeDelta::FromMilliseconds(300); |
| 223 | factory.GetProxy(&delegate, params); |
| 224 | EXPECT_TRUE(done.TimedWait(base::TimeDelta::FromSeconds(1))); |
| 225 | |
| 226 | EXPECT_CALL(delegate, Disconnected()); |
| 227 | factory.ReleaseProxy(&delegate, params.profile); |
| 228 | } |
| 229 | |
| 230 | TEST(ChromeProxy, LaunchChrome) { |
| 231 | base::WaitableEvent connected(false, false); |
| 232 | StrictMock<MockChromeProxyDelegate> delegate; |
| 233 | ChromeProxyFactory factory; |
| 234 | |
| 235 | ProxyParams params; |
| 236 | params.profile = "Adam N. Epilinter"; |
| 237 | params.timeout = base::TimeDelta::FromSeconds(10); |
| 238 | |
| 239 | EXPECT_CALL(delegate, tab_handle()).WillRepeatedly(Return(0)); |
| 240 | EXPECT_CALL(delegate, Connected(NotNull())) |
| 241 | .WillOnce(InvokeWithoutArgs(&connected, &base::WaitableEvent::Signal)); |
| 242 | |
| 243 | factory.GetProxy(&delegate, params); |
| 244 | EXPECT_TRUE(connected.TimedWait(base::TimeDelta::FromSeconds(15))); |
| 245 | |
| 246 | EXPECT_CALL(delegate, Disconnected()); |
| 247 | factory.ReleaseProxy(&delegate, params.profile); |
| 248 | } |
| 249 | |
[email protected] | 138dc7d | 2010-10-12 19:47:18 | [diff] [blame] | 250 | // Test that a channel error results in Completed_XYZ(false, ) called if |
| 251 | // the synchronious XYZ message has been sent. |
| 252 | TEST(ChromeProxy, ChannelError) { |
| 253 | base::WaitableEvent connected(false, false); |
| 254 | StrictMock<MockCFProxyTraits> api; |
| 255 | StrictMock<MockChromeProxyDelegate> delegate; |
| 256 | StrictMock<MockFactory> factory; |
| 257 | CFProxy* proxy = new CFProxy(&api); |
| 258 | |
| 259 | ProxyParams params; |
| 260 | params.profile = "Adam N. Epilinter"; |
| 261 | params.timeout = base::TimeDelta::FromMilliseconds(300); |
| 262 | |
| 263 | testing::InSequence s; |
| 264 | |
| 265 | EXPECT_CALL(factory, CreateProxy()).WillOnce(Return(proxy)); |
| 266 | EXPECT_CALL(api, DoCreateChannel(_, proxy)).WillOnce(Return(&api.sender)); |
| 267 | EXPECT_CALL(api, LaunchApp(_)).WillOnce(DoAll( |
| 268 | API_FIRE_CONNECT(api, base::TimeDelta::FromMilliseconds(10)), |
| 269 | Return(true))); |
| 270 | EXPECT_CALL(delegate, Connected(proxy)) |
| 271 | .WillOnce(DoAll( |
| 272 | InvokeWithoutArgs(CreateFunctor(proxy, &ChromeProxy::ConnectTab, |
| 273 | &delegate, HWND(6), 512)), |
| 274 | InvokeWithoutArgs(&connected, &base::WaitableEvent::Signal))); |
| 275 | |
| 276 | EXPECT_CALL(api.sender, Send(_)); |
[email protected] | 751bf4b | 2010-11-05 22:06:31 | [diff] [blame] | 277 | EXPECT_CALL(delegate, Completed_ConnectToTab(false, _, _, _, _)); |
[email protected] | 138dc7d | 2010-10-12 19:47:18 | [diff] [blame] | 278 | EXPECT_CALL(api, CloseChannel(&api.sender)); |
| 279 | EXPECT_CALL(delegate, PeerLost(_, ChromeProxyDelegate::CHANNEL_ERROR)); |
| 280 | |
| 281 | factory.GetProxy(&delegate, params); |
| 282 | EXPECT_TRUE(connected.TimedWait(base::TimeDelta::FromSeconds(15))); |
| 283 | // Simulate a channel error. |
| 284 | api.FireError(base::TimeDelta::FromMilliseconds(0)); |
| 285 | |
| 286 | // Expectations when the Proxy is destroyed. |
| 287 | EXPECT_CALL(delegate, tab_handle()).WillOnce(Return(0)); |
| 288 | EXPECT_CALL(delegate, Disconnected()); |
| 289 | factory.ReleaseProxy(&delegate, params.profile); |
| 290 | } |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 291 | /////////////////////////////////////////////////////////////////////////////// |
| 292 | namespace { |
| 293 | template <typename M, typename A> |
| 294 | inline IPC::Message* CreateReply(M* m, const A& a) { |
| 295 | IPC::Message* r = IPC::SyncMessage::GenerateReply(m); |
| 296 | if (r) { |
| 297 | M::WriteReplyParams(r, a); |
| 298 | } |
| 299 | return r; |
| 300 | } |
| 301 | |
| 302 | template <typename M, typename A, typename B> |
| 303 | inline IPC::Message* CreateReply(M* m, const A& a, const B& b) { |
| 304 | IPC::Message* r = IPC::SyncMessage::GenerateReply(m); |
| 305 | if (r) { |
| 306 | M::WriteReplyParams(r, a, b); |
| 307 | } |
| 308 | return r; |
| 309 | } |
| 310 | |
| 311 | template <typename M, typename A, typename B, typename C> |
| 312 | inline IPC::Message* CreateReply(M* m, const A& a, const B& b, const C& c) { |
| 313 | IPC::Message* r = IPC::SyncMessage::GenerateReply(m); |
| 314 | if (r) { |
| 315 | M::WriteReplyParams(r, a, b, c); |
| 316 | } |
| 317 | return r; |
| 318 | } |
[email protected] | 751bf4b | 2010-11-05 22:06:31 | [diff] [blame] | 319 | |
| 320 | template <typename M, typename A, typename B, typename C, typename D> |
| 321 | inline IPC::Message* CreateReply(M* m, const A& a, const B& b, const C& c, |
| 322 | const D& d) { |
| 323 | IPC::Message* r = IPC::SyncMessage::GenerateReply(m); |
| 324 | if (r) { |
| 325 | M::WriteReplyParams(r, a, b, c, d); |
| 326 | } |
| 327 | return r; |
| 328 | }} // namespace |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 329 | |
| 330 | DISABLE_RUNNABLE_METHOD_REFCOUNT(SyncMsgSender); |
| 331 | TEST(SyncMsgSender, Deserialize) { |
| 332 | // Note the ipc thread is not actually needed, but we try to be close |
| 333 | // to real-world conditions - that SyncMsgSender works from multiple threads. |
| 334 | base::Thread ipc("ipc"); |
| 335 | ipc.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0)); |
| 336 | |
| 337 | StrictMock<MockChromeProxyDelegate> d1; |
| 338 | TabsMap tab2delegate; |
| 339 | SyncMsgSender queue(&tab2delegate); |
| 340 | |
[email protected] | 751bf4b | 2010-11-05 22:06:31 | [diff] [blame] | 341 | const int kTabHandle = 6; |
| 342 | const int kSessionId = 8; |
| 343 | |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 344 | // Create some sync messages and their replies. |
| 345 | AutomationMsg_InstallExtension m1(0, FilePath(L"c:\\awesome.x"), 0); |
[email protected] | 751bf4b | 2010-11-05 22:06:31 | [diff] [blame] | 346 | AutomationMsg_CreateExternalTab m2(0, IPC::ExternalTabSettings(), 0, 0, 0, 0); |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 347 | scoped_ptr<IPC::Message> r1(CreateReply(&m1, |
| 348 | AUTOMATION_MSG_EXTENSION_INSTALL_SUCCEEDED)); |
[email protected] | 751bf4b | 2010-11-05 22:06:31 | [diff] [blame] | 349 | scoped_ptr<IPC::Message> r2(CreateReply(&m2, (HWND)1, (HWND)2, kTabHandle, |
| 350 | kSessionId)); |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 351 | |
| 352 | queue.QueueSyncMessage(&m1, &d1, NULL); |
| 353 | queue.QueueSyncMessage(&m2, &d1, NULL); |
| 354 | |
| 355 | testing::InSequence s; |
| 356 | EXPECT_CALL(d1, Completed_InstallExtension(true, |
| 357 | AUTOMATION_MSG_EXTENSION_INSTALL_SUCCEEDED, NULL)); |
[email protected] | 751bf4b | 2010-11-05 22:06:31 | [diff] [blame] | 358 | EXPECT_CALL(d1, Completed_CreateTab(true, (HWND)1, (HWND)2, kTabHandle, |
| 359 | kSessionId)); |
[email protected] | 5a8db80 | 2010-10-06 17:34:43 | [diff] [blame] | 360 | |
| 361 | // Execute replies in a worker thread. |
| 362 | ipc.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(&queue, |
| 363 | &SyncMsgSender::OnReplyReceived, r1.get())); |
| 364 | ipc.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(&queue, |
| 365 | &SyncMsgSender::OnReplyReceived, r2.get())); |
| 366 | ipc.Stop(); |
| 367 | |
| 368 | // Expect that tab 6 has been associated with the delegate. |
| 369 | EXPECT_EQ(&d1, tab2delegate[6]); |
| 370 | } |
| 371 | |
| 372 | TEST(SyncMsgSender, OnChannelClosed) { |
| 373 | // TODO(stoyan): implement. |
| 374 | } |
| 375 | |
[email protected] | ccdf73e | 2010-10-07 20:15:19 | [diff] [blame] | 376 | MATCHER_P(EqNavigationInfo, ni, "") { |
| 377 | return arg.navigation_type == ni.navigation_type && |
| 378 | arg.relative_offset == ni.relative_offset && |
| 379 | arg.navigation_index == ni.navigation_index && |
| 380 | arg.title == ni.title && |
| 381 | arg.url == ni.url && |
| 382 | arg.referrer == ni.referrer && |
| 383 | arg.security_style == ni.security_style && |
| 384 | arg.displayed_insecure_content == ni.displayed_insecure_content && |
| 385 | arg.ran_insecure_content == ni.ran_insecure_content; |
| 386 | } |
| 387 | |
| 388 | MATCHER_P(EqMSG, msg, "") { |
| 389 | return arg.hwnd == msg.hwnd && |
| 390 | arg.message == msg.message && |
| 391 | arg.wParam == msg.wParam && |
| 392 | arg.lParam == msg.lParam && |
| 393 | arg.time == msg.time && |
| 394 | arg.pt.x == msg.pt.x && |
| 395 | arg.pt.y == msg.pt.y; |
| 396 | } |
| 397 | |
| 398 | MATCHER_P(EqContextMenuParam, p, "") { |
| 399 | return arg.screen_x == p.screen_x && |
| 400 | arg.screen_y == p.screen_y && |
| 401 | arg.link_url == p.link_url && |
| 402 | arg.unfiltered_link_url == p.unfiltered_link_url && |
| 403 | arg.src_url == p.src_url && |
| 404 | arg.page_url == p.page_url && |
| 405 | arg.frame_url == p.frame_url; |
| 406 | } |
| 407 | |
| 408 | MATCHER_P(EqURLRequest, p, "") { |
| 409 | return arg.url == p.url && |
| 410 | arg.method == p.method && |
| 411 | arg.referrer == p.referrer && |
| 412 | arg.extra_request_headers == p.extra_request_headers && |
| 413 | // TODO(stoyan): scoped_refptr<net::UploadData> upload_data; |
| 414 | arg.resource_type == p.resource_type; |
| 415 | } |
| 416 | |
| 417 | |
| 418 | MATCHER_P(EqAttachExternalTab, p, "") { |
| 419 | return arg.cookie == p.cookie && |
| 420 | arg.url == p.url && |
| 421 | arg.dimensions == p.dimensions && |
| 422 | arg.disposition == p.disposition && |
| 423 | arg.user_gesture == p.user_gesture && |
| 424 | arg.profile_name == p.profile_name; |
| 425 | } |
| 426 | |
| 427 | TEST(Deserialize, DispatchTabMessage) { |
| 428 | testing::InSequence s; |
| 429 | StrictMock<MockChromeProxyDelegate> delegate; |
| 430 | GURL url("http://destination"); |
| 431 | GURL ref("http://referer"); |
| 432 | |
| 433 | // Tuple3<int, int, IPC::NavigationInfo> |
| 434 | int flags = 2; |
| 435 | IPC::NavigationInfo ni = {2, 3, 4, L"title", url, |
| 436 | ref, SECURITY_STYLE_AUTHENTICATION_BROKEN, true, true}; |
| 437 | AutomationMsg_NavigationStateChanged m1(0, 1, flags, ni); |
| 438 | EXPECT_CALL(delegate, NavigationStateChanged(flags, EqNavigationInfo(ni))); |
| 439 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m1)); |
| 440 | |
| 441 | // Tuple2<int, std::wstring> |
| 442 | AutomationMsg_UpdateTargetUrl m2(0, 1, L"hello"); |
| 443 | EXPECT_CALL(delegate, UpdateTargetUrl(StrEq(L"hello"))); |
| 444 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m2)); |
| 445 | |
| 446 | // Tuple2<int, MSG> |
| 447 | MSG wnd_msg = {0, WM_DESTROY, 1, 9, 0x5671, { 11, 12 }}; |
| 448 | AutomationMsg_HandleAccelerator m3(0, 1, wnd_msg); |
| 449 | EXPECT_CALL(delegate, HandleAccelerator(EqMSG(wnd_msg))); |
| 450 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m3)); |
| 451 | |
| 452 | // Tuple2<int, bool> |
| 453 | AutomationMsg_TabbedOut m4(0, 1, true); |
| 454 | EXPECT_CALL(delegate, TabbedOut(true)); |
| 455 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m4)); |
| 456 | |
| 457 | |
| 458 | // Tuple4<int, GURL, GURL, int> |
| 459 | AutomationMsg_OpenURL m5(0, 1, url, ref, 4); |
| 460 | EXPECT_CALL(delegate, OpenURL(url, ref, 4)); |
| 461 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m5)); |
| 462 | |
| 463 | // Tuple3<int, int, GURL> |
| 464 | AutomationMsg_NavigationFailed m6(0, 1, 2, url); |
| 465 | EXPECT_CALL(delegate, NavigationFailed(2, url)); |
| 466 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m6)); |
| 467 | |
| 468 | |
| 469 | // Tuple2<int, IPC::NavigationInfo> |
| 470 | AutomationMsg_DidNavigate m7(0, 1, ni); |
| 471 | EXPECT_CALL(delegate, DidNavigate(EqNavigationInfo(ni))); |
| 472 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m7)); |
| 473 | |
| 474 | |
| 475 | // Tuple2<int, GURL> |
| 476 | AutomationMsg_TabLoaded m8(0, 1, url); |
| 477 | EXPECT_CALL(delegate, TabLoaded(url)); |
| 478 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m8)); |
| 479 | |
| 480 | // Tuple4<int, string, string, string> |
| 481 | std::string msg("Load oranges barrels"); |
| 482 | std::string origin("Brothers Karamazov"); |
| 483 | std::string target("Alexander Ivanovich"); |
| 484 | AutomationMsg_ForwardMessageToExternalHost m9(0, 1, msg, origin, target); |
| 485 | EXPECT_CALL(delegate, MessageToHost(msg, origin, target)); |
| 486 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m9)); |
| 487 | |
| 488 | // Tuple4<int, HANDLE, int, IPC::ContextMenuParams> |
[email protected] | 47af65f | 2010-11-08 21:43:55 | [diff] [blame] | 489 | IPC::MiniContextMenuParams ctxmenu = { 711, 512, GURL("http://link_src"), |
[email protected] | ccdf73e | 2010-10-07 20:15:19 | [diff] [blame] | 490 | GURL("http://unfiltered_link_url"), GURL("http://src_url"), |
| 491 | GURL("http://page_url"), GURL("http://frame_url") }; |
| 492 | AutomationMsg_ForwardContextMenuToExternalHost m10(0, 1, HANDLE(7), 4, |
| 493 | ctxmenu); |
| 494 | EXPECT_CALL(delegate, HandleContextMenu(HANDLE(7), 4, |
| 495 | EqContextMenuParam(ctxmenu))); |
| 496 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m10)); |
| 497 | |
| 498 | // Tuple3<int, int, IPC::AutomationURLRequest> |
| 499 | IPC::AutomationURLRequest url_request = {"url", "post", "referer", |
| 500 | "extra_headers", 0, 3 }; |
| 501 | AutomationMsg_RequestStart m11(0, 1, 7, url_request); |
| 502 | EXPECT_CALL(delegate, Network_Start(7, EqURLRequest(url_request))); |
| 503 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m11)); |
| 504 | |
| 505 | // Tuple3<int, int, int> |
| 506 | AutomationMsg_RequestRead m12(0, 1, 7, 16384); |
| 507 | EXPECT_CALL(delegate, Network_Read(7, 16384)); |
| 508 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m12)); |
| 509 | |
| 510 | // Tuple3<int, int, URLRequestStatus> |
| 511 | AutomationMsg_RequestEnd m13(0, 1, 7, URLRequestStatus()); |
| 512 | EXPECT_CALL(delegate, Network_End(7, _)); |
| 513 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m13)); |
| 514 | |
| 515 | // Tuple2<int, int> |
| 516 | AutomationMsg_DownloadRequestInHost m14(0, 1, 7); |
| 517 | EXPECT_CALL(delegate, Network_DownloadInHost(7)); |
| 518 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m14)); |
| 519 | |
| 520 | // Tuple3<int, GURL, string> |
| 521 | AutomationMsg_SetCookieAsync m15(0, 1, url, "cake=big"); |
| 522 | EXPECT_CALL(delegate, SetCookie(url, "cake=big")); |
| 523 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m15)); |
| 524 | |
| 525 | // Tuple2<int, IPC::AttachExternalTabParams> |
| 526 | IPC::AttachExternalTabParams ext_tab = { 0xFEDCBA0987654321i64, url, |
| 527 | gfx::Rect(6, 9, 123, 999), 1, false, "theprofile" }; |
| 528 | AutomationMsg_AttachExternalTab m16(0, 1, ext_tab); |
| 529 | EXPECT_CALL(delegate, AttachTab(EqAttachExternalTab(ext_tab))); |
| 530 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m16)); |
| 531 | |
| 532 | // Tuple2<int, int> |
| 533 | AutomationMsg_RequestGoToHistoryEntryOffset m17(0, 1, -4); |
| 534 | EXPECT_CALL(delegate, GoToHistoryOffset(-4)); |
| 535 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m17)); |
| 536 | |
| 537 | // Tuple3<int, GURL, int> |
| 538 | AutomationMsg_GetCookiesFromHost m18(0, 1, url, 903); |
| 539 | EXPECT_CALL(delegate, GetCookies(url, 903)); |
| 540 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m18)); |
| 541 | |
| 542 | AutomationMsg_CloseExternalTab m19(0, 1); |
| 543 | EXPECT_CALL(delegate, TabClosed()); |
| 544 | EXPECT_TRUE(DispatchTabMessageToDelegate(&delegate, m19)); |
| 545 | } |