1 // Copyright 2014 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.
5 #include "content/renderer/screen_orientation/screen_orientation_dispatcher.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "content/common/screen_orientation_messages.h"
12 #include "content/public/test/test_utils.h"
13 #include "ipc/ipc_test_sink.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/platform/WebLockOrientationCallback.h"
19 // MockLockOrientationCallback is an implementation of
20 // WebLockOrientationCallback and takes a LockOrientationResultHolder* as a
21 // parameter when being constructed. The |results_| pointer is owned by the
22 // caller and not by the callback object. The intent being that as soon as the
23 // callback is resolved, it will be killed so we use the
24 // LockOrientationResultHolder to know in which state the callback object is at
26 class MockLockOrientationCallback
: public blink::WebLockOrientationCallback
{
28 struct LockOrientationResultHolder
{
29 LockOrientationResultHolder()
30 : succeeded_(false), failed_(false) {}
34 blink::WebLockOrientationError error_
;
37 explicit MockLockOrientationCallback(LockOrientationResultHolder
* results
)
38 : results_(results
) {}
40 virtual void onSuccess() {
41 results_
->succeeded_
= true;
44 virtual void onError(blink::WebLockOrientationError error
) {
45 results_
->failed_
= true;
46 results_
->error_
= error
;
50 virtual ~MockLockOrientationCallback() {}
52 LockOrientationResultHolder
* results_
;
55 class ScreenOrientationDispatcherWithSink
: public ScreenOrientationDispatcher
{
57 explicit ScreenOrientationDispatcherWithSink(IPC::TestSink
* sink
)
58 :ScreenOrientationDispatcher(NULL
) , sink_(sink
) {
61 bool Send(IPC::Message
* message
) override
{ return sink_
->Send(message
); }
66 class ScreenOrientationDispatcherTest
: public testing::Test
{
68 void SetUp() override
{
69 dispatcher_
.reset(new ScreenOrientationDispatcherWithSink(&sink_
));
72 int GetFirstLockRequestIdFromSink() {
73 const IPC::Message
* msg
= sink().GetFirstMessageMatching(
74 ScreenOrientationHostMsg_LockRequest::ID
);
75 EXPECT_TRUE(msg
!= NULL
);
77 base::Tuple
<blink::WebScreenOrientationLockType
, int> params
;
78 ScreenOrientationHostMsg_LockRequest::Read(msg
, ¶ms
);
79 return base::get
<1>(params
);
82 IPC::TestSink
& sink() {
86 void LockOrientation(blink::WebScreenOrientationLockType orientation
,
87 blink::WebLockOrientationCallback
* callback
) {
88 dispatcher_
->lockOrientation(orientation
, callback
);
91 void UnlockOrientation() {
92 dispatcher_
->unlockOrientation();
95 void OnMessageReceived(const IPC::Message
& message
) {
96 dispatcher_
->OnMessageReceived(message
);
99 int routing_id() const {
100 // We return a fake routing_id() in the context of this test.
105 scoped_ptr
<ScreenOrientationDispatcher
> dispatcher_
;
108 // Test that calling lockOrientation() followed by unlockOrientation() cancel
109 // the lockOrientation().
110 TEST_F(ScreenOrientationDispatcherTest
, CancelPending_Unlocking
) {
111 MockLockOrientationCallback::LockOrientationResultHolder callback_results
;
112 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary
,
113 new MockLockOrientationCallback(&callback_results
));
116 EXPECT_FALSE(callback_results
.succeeded_
);
117 EXPECT_TRUE(callback_results
.failed_
);
118 EXPECT_EQ(blink::WebLockOrientationErrorCanceled
, callback_results
.error_
);
121 // Test that calling lockOrientation() twice cancel the first lockOrientation().
122 TEST_F(ScreenOrientationDispatcherTest
, CancelPending_DoubleLock
) {
123 MockLockOrientationCallback::LockOrientationResultHolder callback_results
;
124 // We create the object to prevent leaks but never actually use it.
125 MockLockOrientationCallback::LockOrientationResultHolder callback_results2
;
127 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary
,
128 new MockLockOrientationCallback(&callback_results
));
129 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary
,
130 new MockLockOrientationCallback(&callback_results2
));
132 EXPECT_FALSE(callback_results
.succeeded_
);
133 EXPECT_TRUE(callback_results
.failed_
);
134 EXPECT_EQ(blink::WebLockOrientationErrorCanceled
, callback_results
.error_
);
137 // Test that when a LockError message is received, the request is set as failed
138 // with the correct values.
139 TEST_F(ScreenOrientationDispatcherTest
, LockRequest_Error
) {
140 std::list
<blink::WebLockOrientationError
> errors
;
141 errors
.push_back(blink::WebLockOrientationErrorNotAvailable
);
143 blink::WebLockOrientationErrorFullScreenRequired
);
144 errors
.push_back(blink::WebLockOrientationErrorCanceled
);
146 for (std::list
<blink::WebLockOrientationError
>::const_iterator
147 it
= errors
.begin(); it
!= errors
.end(); ++it
) {
148 MockLockOrientationCallback::LockOrientationResultHolder callback_results
;
149 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary
,
150 new MockLockOrientationCallback(&callback_results
));
152 int request_id
= GetFirstLockRequestIdFromSink();
154 ScreenOrientationMsg_LockError(routing_id(), request_id
, *it
));
156 EXPECT_FALSE(callback_results
.succeeded_
);
157 EXPECT_TRUE(callback_results
.failed_
);
158 EXPECT_EQ(*it
, callback_results
.error_
);
160 sink().ClearMessages();
164 // Test that when a LockSuccess message is received, the request is set as
166 TEST_F(ScreenOrientationDispatcherTest
, LockRequest_Success
) {
167 MockLockOrientationCallback::LockOrientationResultHolder callback_results
;
168 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary
,
169 new MockLockOrientationCallback(&callback_results
));
171 int request_id
= GetFirstLockRequestIdFromSink();
172 OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
175 EXPECT_TRUE(callback_results
.succeeded_
);
176 EXPECT_FALSE(callback_results
.failed_
);
178 sink().ClearMessages();
181 // Test an edge case: a LockSuccess is received but it matches no pending
183 TEST_F(ScreenOrientationDispatcherTest
, SuccessForUnknownRequest
) {
184 MockLockOrientationCallback::LockOrientationResultHolder callback_results
;
185 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary
,
186 new MockLockOrientationCallback(&callback_results
));
188 int request_id
= GetFirstLockRequestIdFromSink();
189 OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
192 EXPECT_FALSE(callback_results
.succeeded_
);
193 EXPECT_FALSE(callback_results
.failed_
);
196 // Test an edge case: a LockError is received but it matches no pending
198 TEST_F(ScreenOrientationDispatcherTest
, ErrorForUnknownRequest
) {
199 MockLockOrientationCallback::LockOrientationResultHolder callback_results
;
200 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary
,
201 new MockLockOrientationCallback(&callback_results
));
203 int request_id
= GetFirstLockRequestIdFromSink();
204 OnMessageReceived(ScreenOrientationMsg_LockError(
205 routing_id(), request_id
+ 1, blink::WebLockOrientationErrorCanceled
));
207 EXPECT_FALSE(callback_results
.succeeded_
);
208 EXPECT_FALSE(callback_results
.failed_
);
211 // Test the following scenario:
212 // - request1 is received by the dispatcher;
213 // - request2 is received by the dispatcher;
214 // - request1 is rejected;
215 // - request1 success response is received.
216 // Expected: request1 is still rejected, request2 has not been set as succeeded.
217 TEST_F(ScreenOrientationDispatcherTest
, RaceScenario
) {
218 MockLockOrientationCallback::LockOrientationResultHolder callback_results1
;
219 MockLockOrientationCallback::LockOrientationResultHolder callback_results2
;
221 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary
,
222 new MockLockOrientationCallback(&callback_results1
));
223 int request_id1
= GetFirstLockRequestIdFromSink();
225 LockOrientation(blink::WebScreenOrientationLockLandscapePrimary
,
226 new MockLockOrientationCallback(&callback_results2
));
228 // callback_results1 must be rejected, tested in CancelPending_DoubleLock.
230 OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
233 // First request is still rejected.
234 EXPECT_FALSE(callback_results1
.succeeded_
);
235 EXPECT_TRUE(callback_results1
.failed_
);
236 EXPECT_EQ(blink::WebLockOrientationErrorCanceled
, callback_results1
.error_
);
238 // Second request is still pending.
239 EXPECT_FALSE(callback_results2
.succeeded_
);
240 EXPECT_FALSE(callback_results2
.failed_
);
243 } // namespace content