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 "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 :
27 public blink::WebLockOrientationCallback {
29 struct LockOrientationResultHolder {
30 LockOrientationResultHolder()
31 : succeeded_(false), failed_(false) {}
35 blink::WebLockOrientationError error_;
38 explicit MockLockOrientationCallback(LockOrientationResultHolder* results)
39 : results_(results) {}
41 virtual void onSuccess() {
42 results_->succeeded_ = true;
45 virtual void onError(blink::WebLockOrientationError error) {
46 results_->failed_ = true;
47 results_->error_ = error;
51 virtual ~MockLockOrientationCallback() {}
53 LockOrientationResultHolder* results_;
56 class ScreenOrientationDispatcherWithSink : public ScreenOrientationDispatcher {
58 explicit ScreenOrientationDispatcherWithSink(IPC::TestSink* sink)
59 :ScreenOrientationDispatcher(NULL) , sink_(sink) {
62 bool Send(IPC::Message* message) override { return sink_->Send(message); }
67 class ScreenOrientationDispatcherTest : public testing::Test {
69 void SetUp() override {
70 dispatcher_.reset(new ScreenOrientationDispatcherWithSink(&sink_));
73 int GetFirstLockRequestIdFromSink() {
74 const IPC::Message* msg = sink().GetFirstMessageMatching(
75 ScreenOrientationHostMsg_LockRequest::ID);
76 EXPECT_TRUE(msg != NULL);
78 Tuple2<blink::WebScreenOrientationLockType,int> params;
79 ScreenOrientationHostMsg_LockRequest::Read(msg, ¶ms);
83 IPC::TestSink& sink() {
87 void LockOrientation(blink::WebScreenOrientationLockType orientation,
88 blink::WebLockOrientationCallback* callback) {
89 dispatcher_->lockOrientation(orientation, callback);
92 void UnlockOrientation() {
93 dispatcher_->unlockOrientation();
96 void OnMessageReceived(const IPC::Message& message) {
97 dispatcher_->OnMessageReceived(message);
100 int routing_id() const {
101 // We return a fake routing_id() in the context of this test.
106 scoped_ptr<ScreenOrientationDispatcher> dispatcher_;
109 // Test that calling lockOrientation() followed by unlockOrientation() cancel
110 // the lockOrientation().
111 TEST_F(ScreenOrientationDispatcherTest, CancelPending_Unlocking) {
112 MockLockOrientationCallback::LockOrientationResultHolder callback_results;
113 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
114 new MockLockOrientationCallback(&callback_results));
117 EXPECT_FALSE(callback_results.succeeded_);
118 EXPECT_TRUE(callback_results.failed_);
119 EXPECT_EQ(blink::WebLockOrientationErrorCanceled, callback_results.error_);
122 // Test that calling lockOrientation() twice cancel the first lockOrientation().
123 TEST_F(ScreenOrientationDispatcherTest, CancelPending_DoubleLock) {
124 MockLockOrientationCallback::LockOrientationResultHolder callback_results;
125 // We create the object to prevent leaks but never actually use it.
126 MockLockOrientationCallback::LockOrientationResultHolder callback_results2;
128 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
129 new MockLockOrientationCallback(&callback_results));
130 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
131 new MockLockOrientationCallback(&callback_results2));
133 EXPECT_FALSE(callback_results.succeeded_);
134 EXPECT_TRUE(callback_results.failed_);
135 EXPECT_EQ(blink::WebLockOrientationErrorCanceled, callback_results.error_);
138 // Test that when a LockError message is received, the request is set as failed
139 // with the correct values.
140 TEST_F(ScreenOrientationDispatcherTest, LockRequest_Error) {
141 std::list<blink::WebLockOrientationError> errors;
142 errors.push_back(blink::WebLockOrientationErrorNotAvailable);
144 blink::WebLockOrientationErrorFullScreenRequired);
145 errors.push_back(blink::WebLockOrientationErrorCanceled);
147 for (std::list<blink::WebLockOrientationError>::const_iterator
148 it = errors.begin(); it != errors.end(); ++it) {
149 MockLockOrientationCallback::LockOrientationResultHolder callback_results;
150 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
151 new MockLockOrientationCallback(&callback_results));
153 int request_id = GetFirstLockRequestIdFromSink();
155 ScreenOrientationMsg_LockError(routing_id(), request_id, *it));
157 EXPECT_FALSE(callback_results.succeeded_);
158 EXPECT_TRUE(callback_results.failed_);
159 EXPECT_EQ(*it, callback_results.error_);
161 sink().ClearMessages();
165 // Test that when a LockSuccess message is received, the request is set as
167 TEST_F(ScreenOrientationDispatcherTest, LockRequest_Success) {
168 MockLockOrientationCallback::LockOrientationResultHolder callback_results;
169 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
170 new MockLockOrientationCallback(&callback_results));
172 int request_id = GetFirstLockRequestIdFromSink();
173 OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
176 EXPECT_TRUE(callback_results.succeeded_);
177 EXPECT_FALSE(callback_results.failed_);
179 sink().ClearMessages();
182 // Test an edge case: a LockSuccess is received but it matches no pending
184 TEST_F(ScreenOrientationDispatcherTest, SuccessForUnknownRequest) {
185 MockLockOrientationCallback::LockOrientationResultHolder callback_results;
186 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
187 new MockLockOrientationCallback(&callback_results));
189 int request_id = GetFirstLockRequestIdFromSink();
190 OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
193 EXPECT_FALSE(callback_results.succeeded_);
194 EXPECT_FALSE(callback_results.failed_);
197 // Test an edge case: a LockError is received but it matches no pending
199 TEST_F(ScreenOrientationDispatcherTest, ErrorForUnknownRequest) {
200 MockLockOrientationCallback::LockOrientationResultHolder callback_results;
201 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
202 new MockLockOrientationCallback(&callback_results));
204 int request_id = GetFirstLockRequestIdFromSink();
205 OnMessageReceived(ScreenOrientationMsg_LockError(
206 routing_id(), request_id + 1, blink::WebLockOrientationErrorCanceled));
208 EXPECT_FALSE(callback_results.succeeded_);
209 EXPECT_FALSE(callback_results.failed_);
212 // Test the following scenario:
213 // - request1 is received by the dispatcher;
214 // - request2 is received by the dispatcher;
215 // - request1 is rejected;
216 // - request1 success response is received.
217 // Expected: request1 is still rejected, request2 has not been set as succeeded.
218 TEST_F(ScreenOrientationDispatcherTest, RaceScenario) {
219 MockLockOrientationCallback::LockOrientationResultHolder callback_results1;
220 MockLockOrientationCallback::LockOrientationResultHolder callback_results2;
222 LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
223 new MockLockOrientationCallback(&callback_results1));
224 int request_id1 = GetFirstLockRequestIdFromSink();
226 LockOrientation(blink::WebScreenOrientationLockLandscapePrimary,
227 new MockLockOrientationCallback(&callback_results2));
229 // callback_results1 must be rejected, tested in CancelPending_DoubleLock.
231 OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
234 // First request is still rejected.
235 EXPECT_FALSE(callback_results1.succeeded_);
236 EXPECT_TRUE(callback_results1.failed_);
237 EXPECT_EQ(blink::WebLockOrientationErrorCanceled, callback_results1.error_);
239 // Second request is still pending.
240 EXPECT_FALSE(callback_results2.succeeded_);
241 EXPECT_FALSE(callback_results2.failed_);
244 } // namespace content