summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormlamouri@chromium.org <mlamouri@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-05 17:01:49 +0000
committermlamouri@chromium.org <mlamouri@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-05 17:01:49 +0000
commitb6e8531e12a898ceb96a3f6b54e957db05c8f78f (patch)
tree084f8495d29215be4379e537dc09cc5780ead37c
parente7deba3cbe8e7a081d331ee547efd8755153e183 (diff)
downloadchromium_src-b6e8531e12a898ceb96a3f6b54e957db05c8f78f.zip
chromium_src-b6e8531e12a898ceb96a3f6b54e957db05c8f78f.tar.gz
chromium_src-b6e8531e12a898ceb96a3f6b54e957db05c8f78f.tar.bz2
Basic Promise-based lockOrientation() implementation in content/.
The only missing bit is to have proper values when the promise is succussfully resolved. BUG=162827 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=275058 Review URL: https://codereview.chromium.org/298193003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275168 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/screen_orientation/screen_orientation_dispatcher_host.cc16
-rw-r--r--content/browser/screen_orientation/screen_orientation_dispatcher_host.h6
-rw-r--r--content/browser/screen_orientation/screen_orientation_dispatcher_host_unittest.cc95
-rw-r--r--content/common/DEPS1
-rw-r--r--content/common/screen_orientation_messages.h32
-rw-r--r--content/renderer/renderer_webkitplatformsupport_impl.cc24
-rw-r--r--content/renderer/renderer_webkitplatformsupport_impl.h4
-rw-r--r--content/renderer/screen_orientation/screen_orientation_dispatcher.cc61
-rw-r--r--content/renderer/screen_orientation/screen_orientation_dispatcher.h37
-rw-r--r--content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc234
10 files changed, 472 insertions, 38 deletions
diff --git a/content/browser/screen_orientation/screen_orientation_dispatcher_host.cc b/content/browser/screen_orientation/screen_orientation_dispatcher_host.cc
index ccc3e22..3bb494d 100644
--- a/content/browser/screen_orientation/screen_orientation_dispatcher_host.cc
+++ b/content/browser/screen_orientation/screen_orientation_dispatcher_host.cc
@@ -23,7 +23,7 @@ bool ScreenOrientationDispatcherHost::OnMessageReceived(
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ScreenOrientationDispatcherHost, message)
- IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_Lock, OnLockRequest)
+ IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_LockRequest, OnLockRequest)
IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_Unlock, OnUnlockRequest)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -42,10 +42,20 @@ void ScreenOrientationDispatcherHost::SetProviderForTests(
}
void ScreenOrientationDispatcherHost::OnLockRequest(
- blink::WebScreenOrientationLockType orientation) {
- if (!provider_.get())
+ blink::WebScreenOrientationLockType orientation,
+ int request_id) {
+ if (!provider_) {
+ Send(new ScreenOrientationMsg_LockError(
+ request_id,
+ blink::WebLockOrientationCallback::ErrorTypeNotAvailable));
return;
+ }
+ // TODO(mlamouri): pass real values.
+ Send(new ScreenOrientationMsg_LockSuccess(
+ request_id,
+ 0,
+ blink::WebScreenOrientationPortraitPrimary));
provider_->LockOrientation(orientation);
}
diff --git a/content/browser/screen_orientation/screen_orientation_dispatcher_host.h b/content/browser/screen_orientation/screen_orientation_dispatcher_host.h
index 401a9e0..363c08c 100644
--- a/content/browser/screen_orientation/screen_orientation_dispatcher_host.h
+++ b/content/browser/screen_orientation/screen_orientation_dispatcher_host.h
@@ -28,10 +28,12 @@ class CONTENT_EXPORT ScreenOrientationDispatcherHost
void SetProviderForTests(ScreenOrientationProvider* provider);
- private:
+ protected:
virtual ~ScreenOrientationDispatcherHost();
- void OnLockRequest(blink::WebScreenOrientationLockType orientations);
+ private:
+ void OnLockRequest(blink::WebScreenOrientationLockType orientation,
+ int request_id);
void OnUnlockRequest();
static ScreenOrientationProvider* CreateProvider();
diff --git a/content/browser/screen_orientation/screen_orientation_dispatcher_host_unittest.cc b/content/browser/screen_orientation/screen_orientation_dispatcher_host_unittest.cc
index 67f81de..b652413 100644
--- a/content/browser/screen_orientation/screen_orientation_dispatcher_host_unittest.cc
+++ b/content/browser/screen_orientation/screen_orientation_dispatcher_host_unittest.cc
@@ -7,7 +7,12 @@
#include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h"
#include "content/common/screen_orientation_messages.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
+#include "ipc/ipc_test_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -21,7 +26,6 @@ class MockScreenOrientationProvider : public ScreenOrientationProvider {
virtual void LockOrientation(blink::WebScreenOrientationLockType orientation)
OVERRIDE {
orientation_ = orientation;
-
}
virtual void UnlockOrientation() OVERRIDE {
@@ -45,12 +49,32 @@ class MockScreenOrientationProvider : public ScreenOrientationProvider {
DISALLOW_COPY_AND_ASSIGN(MockScreenOrientationProvider);
};
+class ScreenOrientationDispatcherHostWithSink FINAL :
+ public ScreenOrientationDispatcherHost {
+ public:
+ explicit ScreenOrientationDispatcherHostWithSink(IPC::TestSink* sink)
+ : ScreenOrientationDispatcherHost() , sink_(sink) {}
+
+ virtual bool Send(IPC::Message* message) OVERRIDE {
+ return sink_->Send(message);
+ }
+
+ private:
+ virtual ~ScreenOrientationDispatcherHostWithSink() { }
+
+ IPC::TestSink* sink_;
+};
+
class ScreenOrientationDispatcherHostTest : public testing::Test {
protected:
+ virtual ScreenOrientationDispatcherHost* CreateDispatcher() {
+ return new ScreenOrientationDispatcherHost();
+ }
+
virtual void SetUp() OVERRIDE {
provider_ = new MockScreenOrientationProvider();
- dispatcher_ = new ScreenOrientationDispatcherHost();
+ dispatcher_ = CreateDispatcher();
dispatcher_->SetProviderForTests(provider_);
}
@@ -59,19 +83,25 @@ class ScreenOrientationDispatcherHostTest : public testing::Test {
scoped_refptr<ScreenOrientationDispatcherHost> dispatcher_;
};
-// Test that a NULL provider is correctly handled.
-TEST_F(ScreenOrientationDispatcherHostTest, NullProvider) {
- dispatcher_->SetProviderForTests(NULL);
+class ScreenOrientationDispatcherHostWithSinkTest :
+ public ScreenOrientationDispatcherHostTest {
+ protected:
+ virtual ScreenOrientationDispatcherHost* CreateDispatcher() OVERRIDE {
+ return new ScreenOrientationDispatcherHostWithSink(&sink_);
+ }
- bool message_was_handled = dispatcher_->OnMessageReceived(
- ScreenOrientationHostMsg_Lock(
- blink::WebScreenOrientationLockPortraitPrimary));
- EXPECT_TRUE(message_was_handled);
-}
+ const IPC::TestSink& sink() const {
+ return sink_;
+ }
+
+ IPC::TestSink sink_;
+};
// Test that when receiving a lock message, it is correctly dispatched to the
// ScreenOrientationProvider.
-TEST_F(ScreenOrientationDispatcherHostTest, ProviderLock) {
+// We don't actually need this to be a *WithSinkTest but otherwise the IPC
+// messages are detected as leaked.
+TEST_F(ScreenOrientationDispatcherHostWithSinkTest, ProviderLock) {
// If we change this array, update |orientationsToTestCount| below.
blink::WebScreenOrientationLockType orientationsToTest[] = {
blink::WebScreenOrientationLockPortraitPrimary,
@@ -93,7 +123,7 @@ TEST_F(ScreenOrientationDispatcherHostTest, ProviderLock) {
blink::WebScreenOrientationLockType orientation = orientationsToTest[i];
message_was_handled = dispatcher_->OnMessageReceived(
- ScreenOrientationHostMsg_Lock(orientation));
+ ScreenOrientationHostMsg_LockRequest(orientation, 0));
EXPECT_TRUE(message_was_handled);
EXPECT_EQ(orientation, provider_->orientation());
@@ -110,4 +140,45 @@ TEST_F(ScreenOrientationDispatcherHostTest, ProviderUnlock) {
EXPECT_TRUE(provider_->unlock_called());
}
+// Test that when there is no provider, a LockRequest fails with the appropriate
+// ErrorType.
+TEST_F(ScreenOrientationDispatcherHostWithSinkTest, NoProvider_LockError) {
+ dispatcher_->SetProviderForTests(NULL);
+
+ const int request_id = 3;
+ dispatcher_->OnMessageReceived(ScreenOrientationHostMsg_LockRequest(
+ blink::WebScreenOrientationLockPortraitPrimary, request_id));
+
+ EXPECT_EQ(1u, sink().message_count());
+
+ const IPC::Message* msg = sink().GetFirstMessageMatching(
+ ScreenOrientationMsg_LockError::ID);
+ EXPECT_TRUE(msg != NULL);
+
+ Tuple2<int, blink::WebLockOrientationCallback::ErrorType> params;
+ ScreenOrientationMsg_LockError::Read(msg, &params);
+ EXPECT_EQ(request_id, params.a);
+ EXPECT_EQ(blink::WebLockOrientationCallback::ErrorTypeNotAvailable, params.b);
+}
+
+// Test that when there is a provider, we always send a success response back to
+// the renderer.
+// TODO(mlamouri): we currently do not test the content of the message because
+// it currently contains dummy values.
+TEST_F(ScreenOrientationDispatcherHostWithSinkTest, WithProvider_LockSuccess) {
+ const int request_id = 42;
+ dispatcher_->OnMessageReceived(ScreenOrientationHostMsg_LockRequest(
+ blink::WebScreenOrientationLockPortraitPrimary, request_id));
+
+ EXPECT_EQ(1u, sink().message_count());
+
+ const IPC::Message* msg = sink().GetFirstMessageMatching(
+ ScreenOrientationMsg_LockSuccess::ID);
+ EXPECT_TRUE(msg != NULL);
+
+ Tuple3<int, unsigned, blink::WebScreenOrientationType> params;
+ ScreenOrientationMsg_LockSuccess::Read(msg, &params);
+ EXPECT_EQ(request_id, params.a);
+}
+
} // namespace content
diff --git a/content/common/DEPS b/content/common/DEPS
index afbcc16..7d2d0e7 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -21,6 +21,7 @@ include_rules = [
"+third_party/WebKit/public/platform/WebIDBCursor.h",
"+third_party/WebKit/public/platform/WebIDBDatabase.h",
"+third_party/WebKit/public/platform/WebIDBTypes.h",
+ "+third_party/WebKit/public/platform/WebLockOrientationCallback.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenOrientationLockType.h",
"+third_party/WebKit/public/platform/WebScreenOrientationType.h",
diff --git a/content/common/screen_orientation_messages.h b/content/common/screen_orientation_messages.h
index 9ea3057..5a845e7 100644
--- a/content/common/screen_orientation_messages.h
+++ b/content/common/screen_orientation_messages.h
@@ -7,6 +7,7 @@
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/WebLockOrientationCallback.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
@@ -21,16 +22,41 @@ IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScreenOrientationType,
IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScreenOrientationLockType,
blink::WebScreenOrientationLockDefault,
blink::WebScreenOrientationLockPortrait)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(
+ blink::WebLockOrientationCallback::ErrorType,
+ blink::WebLockOrientationCallback::ErrorTypeNotAvailable,
+ blink::WebLockOrientationCallback::ErrorTypeCanceled)
// The browser process informs the renderer process that the screen orientation
// has changed. |orientation| contains the new screen orientation in degrees.
IPC_MESSAGE_CONTROL1(ScreenOrientationMsg_OrientationChange,
blink::WebScreenOrientationType /* orientation */ )
+// The browser process' response to a ScreenOrientationHostMsg_LockRequest when
+// the lock actually succeeded. The message includes the new |angle| and |type|
+// of orientation. The |request_id| passed when receiving the request is passed
+// back so the renderer process can associate the response to the right request.
+IPC_MESSAGE_CONTROL3(ScreenOrientationMsg_LockSuccess,
+ int, /* request_id */
+ unsigned, /* angle */
+ blink::WebScreenOrientationType /* type */)
+
+// The browser process' response to a ScreenOrientationHostMsg_LockRequest when
+// the lock actually failed. The message includes the |error| type. The
+// |request_id| passed when receiving the request is passed back so the renderer
+// process can associate the response to the right request.
+IPC_MESSAGE_CONTROL2(ScreenOrientationMsg_LockError,
+ int, /* request_id */
+ blink::WebLockOrientationCallback::ErrorType /* error */);
+
// The renderer process requests the browser process to lock the screen
-// orientation to the specified |orientations|.
-IPC_MESSAGE_CONTROL1(ScreenOrientationHostMsg_Lock,
- blink::WebScreenOrientationLockType /* orientations */ )
+// orientation to the specified |orientations|. The request contains a
+// |request_id| that will have to be passed back to the renderer process when
+// notifying about a success or error (see ScreenOrientationMsg_LockError and
+// ScreenOrientationMsg_LockSuccess).
+IPC_MESSAGE_CONTROL2(ScreenOrientationHostMsg_LockRequest,
+ blink::WebScreenOrientationLockType, /* orientation */
+ int /* request_id */)
// The renderer process requests the browser process to unlock the screen
// orientation.
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc
index 5f9f398..cd8628f 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ b/content/renderer/renderer_webkitplatformsupport_impl.cc
@@ -1126,6 +1126,13 @@ void RendererWebKitPlatformSupportImpl::cancelVibration() {
//------------------------------------------------------------------------------
+void RendererWebKitPlatformSupportImpl::EnsureScreenOrientationDispatcher() {
+ if (screen_orientation_dispatcher_)
+ return;
+
+ screen_orientation_dispatcher_.reset(new ScreenOrientationDispatcher());
+}
+
void RendererWebKitPlatformSupportImpl::setScreenOrientationListener(
blink::WebScreenOrientationListener* listener) {
if (RenderThreadImpl::current() &&
@@ -1138,22 +1145,23 @@ void RendererWebKitPlatformSupportImpl::setScreenOrientationListener(
return;
}
- if (!screen_orientation_dispatcher_) {
- screen_orientation_dispatcher_.reset(
- new ScreenOrientationDispatcher(RenderThread::Get()));
- }
+ EnsureScreenOrientationDispatcher();
screen_orientation_dispatcher_->setListener(listener);
}
void RendererWebKitPlatformSupportImpl::lockOrientation(
- blink::WebScreenOrientationLockType orientation) {
+ blink::WebScreenOrientationLockType orientation,
+ blink::WebLockOrientationCallback* callback) {
if (RenderThreadImpl::current() &&
RenderThreadImpl::current()->layout_test_mode()) {
g_test_screen_orientation_controller.Get().UpdateLock(orientation);
return;
}
- RenderThread::Get()->Send(new ScreenOrientationHostMsg_Lock(orientation));
+
+ EnsureScreenOrientationDispatcher();
+ screen_orientation_dispatcher_->LockOrientation(
+ orientation, scoped_ptr<blink::WebLockOrientationCallback>(callback));
}
void RendererWebKitPlatformSupportImpl::unlockOrientation() {
@@ -1162,7 +1170,9 @@ void RendererWebKitPlatformSupportImpl::unlockOrientation() {
g_test_screen_orientation_controller.Get().ResetLock();
return;
}
- RenderThread::Get()->Send(new ScreenOrientationHostMsg_Unlock);
+
+ EnsureScreenOrientationDispatcher();
+ screen_orientation_dispatcher_->UnlockOrientation();
}
// static
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.h b/content/renderer/renderer_webkitplatformsupport_impl.h
index 725a8ec..0dfb4dc 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.h
+++ b/content/renderer/renderer_webkitplatformsupport_impl.h
@@ -148,7 +148,8 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
virtual void cancelVibration();
virtual void setScreenOrientationListener(
blink::WebScreenOrientationListener*);
- virtual void lockOrientation(blink::WebScreenOrientationLockType);
+ virtual void lockOrientation(blink::WebScreenOrientationLockType,
+ blink::WebLockOrientationCallback*);
virtual void unlockOrientation();
virtual void setBatteryStatusListener(
blink::WebBatteryStatusListener* listener);
@@ -196,6 +197,7 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
private:
bool CheckPreparsedJsCachingEnabled() const;
+ void EnsureScreenOrientationDispatcher();
scoped_ptr<RendererClipboardClient> clipboard_client_;
scoped_ptr<WebClipboardImpl> clipboard_;
diff --git a/content/renderer/screen_orientation/screen_orientation_dispatcher.cc b/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
index 3416ec5..280f9c7 100644
--- a/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
+++ b/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
@@ -10,10 +10,12 @@
namespace content {
-ScreenOrientationDispatcher::ScreenOrientationDispatcher(
- RenderThread* thread)
- : listener_(NULL) {
- thread->AddObserver(this);
+ScreenOrientationDispatcher::ScreenOrientationDispatcher()
+ : listener_(NULL) {
+ RenderThread::Get()->AddObserver(this);
+}
+
+ScreenOrientationDispatcher::~ScreenOrientationDispatcher() {
}
bool ScreenOrientationDispatcher::OnControlMessageReceived(
@@ -23,6 +25,10 @@ bool ScreenOrientationDispatcher::OnControlMessageReceived(
IPC_BEGIN_MESSAGE_MAP(ScreenOrientationDispatcher, message)
IPC_MESSAGE_HANDLER(ScreenOrientationMsg_OrientationChange,
OnOrientationChange)
+ IPC_MESSAGE_HANDLER(ScreenOrientationMsg_LockSuccess,
+ OnLockSuccess)
+ IPC_MESSAGE_HANDLER(ScreenOrientationMsg_LockError,
+ OnLockError)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -37,9 +43,56 @@ void ScreenOrientationDispatcher::OnOrientationChange(
listener_->didChangeScreenOrientation(orientation);
}
+void ScreenOrientationDispatcher::OnLockSuccess(
+ int request_id,
+ unsigned angle,
+ blink::WebScreenOrientationType orientation) {
+ blink::WebLockOrientationCallback* callback =
+ pending_callbacks_.Lookup(request_id);
+ if (!callback)
+ return;
+ callback->onSuccess(angle, orientation);
+ pending_callbacks_.Remove(request_id);
+}
+
+void ScreenOrientationDispatcher::OnLockError(
+ int request_id,
+ blink::WebLockOrientationCallback::ErrorType error) {
+ blink::WebLockOrientationCallback* callback =
+ pending_callbacks_.Lookup(request_id);
+ if (!callback)
+ return;
+ callback->onError(error);
+ pending_callbacks_.Remove(request_id);
+}
+
void ScreenOrientationDispatcher::setListener(
blink::WebScreenOrientationListener* listener) {
listener_ = listener;
}
+void ScreenOrientationDispatcher::CancelPendingLocks() {
+ for (CallbackMap::Iterator<blink::WebLockOrientationCallback>
+ iterator(&pending_callbacks_); !iterator.IsAtEnd(); iterator.Advance()) {
+ iterator.GetCurrentValue()->onError(
+ blink::WebLockOrientationCallback::ErrorTypeCanceled);
+ pending_callbacks_.Remove(iterator.GetCurrentKey());
+ }
+}
+
+void ScreenOrientationDispatcher::LockOrientation(
+ blink::WebScreenOrientationLockType orientation,
+ scoped_ptr<blink::WebLockOrientationCallback> callback) {
+ CancelPendingLocks();
+
+ int request_id = pending_callbacks_.Add(callback.release());
+ RenderThread::Get()->Send(
+ new ScreenOrientationHostMsg_LockRequest(orientation, request_id));
+}
+
+void ScreenOrientationDispatcher::UnlockOrientation() {
+ CancelPendingLocks();
+ RenderThread::Get()->Send(new ScreenOrientationHostMsg_Unlock);
+}
+
} // namespace content
diff --git a/content/renderer/screen_orientation/screen_orientation_dispatcher.h b/content/renderer/screen_orientation/screen_orientation_dispatcher.h
index 5aadd6e..b34e173 100644
--- a/content/renderer/screen_orientation/screen_orientation_dispatcher.h
+++ b/content/renderer/screen_orientation/screen_orientation_dispatcher.h
@@ -5,8 +5,12 @@
#ifndef CONTENT_RENDERER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DISPATCHER_H_
#define CONTENT_RENDERER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DISPATCHER_H_
+#include "base/id_map.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "content/public/renderer/render_process_observer.h"
+#include "third_party/WebKit/public/platform/WebLockOrientationCallback.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
namespace blink {
@@ -15,26 +19,49 @@ class WebScreenOrientationListener;
namespace content {
-class RenderThread;
-
// ScreenOrientationDispatcher listens to message from the browser process and
-// dispatch the orientation change ones to the WebScreenOrientationListener.
+// dispatch the orientation change ones to the WebScreenOrientationListener. It
+// also does the bridge between the browser process and Blink with regards to
+// lock orientation request and the handling of WebLockOrientationCallback.
class CONTENT_EXPORT ScreenOrientationDispatcher
: public RenderProcessObserver {
public:
- explicit ScreenOrientationDispatcher(RenderThread*);
- virtual ~ScreenOrientationDispatcher() {}
+ ScreenOrientationDispatcher();
+ virtual ~ScreenOrientationDispatcher();
// RenderProcessObserver
virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
void setListener(blink::WebScreenOrientationListener* listener);
+ // The |callback| is owned by ScreenOrientationDispatcher. It will be assigned
+ // to |pending_callbacks_| that will delete it when the entry will be removed
+ // from the map.
+ void LockOrientation(blink::WebScreenOrientationLockType orientation,
+ scoped_ptr<blink::WebLockOrientationCallback> callback);
+
+ void UnlockOrientation();
+
private:
void OnOrientationChange(blink::WebScreenOrientationType orientation);
+ void OnLockSuccess(int request_id,
+ unsigned angle,
+ blink::WebScreenOrientationType orientation);
+ void OnLockError(int request_id,
+ blink::WebLockOrientationCallback::ErrorType error);
+
+ void CancelPendingLocks();
blink::WebScreenOrientationListener* listener_;
+ // The pending_callbacks_ map is mostly meant to have a unique ID to associate
+ // with every callback going trough the dispatcher. The map will own the
+ // pointer in the sense that it will destroy it when Remove() will be called.
+ // Furthermore, we only expect to have one callback at a time in this map,
+ // which is what IDMap was designed for.
+ typedef IDMap<blink::WebLockOrientationCallback, IDMapOwnPointer> CallbackMap;
+ CallbackMap pending_callbacks_;
+
DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDispatcher);
};
diff --git a/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc b/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
index acc12c2..85bcf01 100644
--- a/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
+++ b/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
@@ -4,12 +4,15 @@
#include "screen_orientation_dispatcher.h"
+#include <list>
+
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/screen_orientation_messages.h"
#include "content/public/test/mock_render_thread.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebLockOrientationCallback.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationListener.h"
namespace content {
@@ -38,6 +41,55 @@ class MockScreenOrientationListener :
DISALLOW_COPY_AND_ASSIGN(MockScreenOrientationListener);
};
+// MockLockOrientationCallback is an implementation of
+// WebLockOrientationCallback and takes a LockOrientationResultHolder* as a
+// parameter when being constructed. The |results_| pointer is owned by the
+// caller and not by the callback object. The intent being that as soon as the
+// callback is resolved, it will be killed so we use the
+// LockOrientationResultHolder to know in which state the callback object is at
+// any time.
+class MockLockOrientationCallback :
+ public blink::WebLockOrientationCallback {
+ public:
+ struct LockOrientationResultHolder {
+ LockOrientationResultHolder()
+ : succeeded_(false), failed_(false) {}
+
+ bool succeeded_;
+ bool failed_;
+ unsigned angle_;
+ blink::WebScreenOrientationType orientation_;
+ blink::WebLockOrientationCallback::ErrorType error_;
+ };
+
+ static scoped_ptr<blink::WebLockOrientationCallback> CreateScoped(
+ LockOrientationResultHolder* results) {
+ return scoped_ptr<blink::WebLockOrientationCallback>(
+ new MockLockOrientationCallback(results));
+ }
+
+ virtual void onSuccess(unsigned angle,
+ blink::WebScreenOrientationType orientation) {
+ results_->succeeded_ = true;
+ results_->angle_ = angle;
+ results_->orientation_ = orientation;
+ }
+
+ virtual void onError(
+ blink::WebLockOrientationCallback::ErrorType error) {
+ results_->failed_ = true;
+ results_->error_ = error;
+ }
+
+ private:
+ explicit MockLockOrientationCallback(LockOrientationResultHolder* results)
+ : results_(results) {}
+
+ virtual ~MockLockOrientationCallback() {}
+
+ LockOrientationResultHolder* results_;
+};
+
MockScreenOrientationListener::MockScreenOrientationListener()
: did_change_screen_orientation_(false),
screen_orientation_(blink::WebScreenOrientationPortraitPrimary) {
@@ -54,10 +106,20 @@ class ScreenOrientationDispatcherTest : public testing::Test {
virtual void SetUp() OVERRIDE {
render_thread_.reset(new MockRenderThread);
listener_.reset(new MockScreenOrientationListener);
- dispatcher_.reset(new ScreenOrientationDispatcher(render_thread_.get()));
+ dispatcher_.reset(new ScreenOrientationDispatcher);
dispatcher_->setListener(listener_.get());
}
+ int GetFirstLockRequestIdFromSink() {
+ const IPC::Message* msg = render_thread_->sink().GetFirstMessageMatching(
+ ScreenOrientationHostMsg_LockRequest::ID);
+ EXPECT_TRUE(msg != NULL);
+
+ Tuple2<blink::WebScreenOrientationLockType,int> params;
+ ScreenOrientationHostMsg_LockRequest::Read(msg, &params);
+ return params.b;
+ }
+
scoped_ptr<MockRenderThread> render_thread_;
scoped_ptr<MockScreenOrientationListener> listener_;
scoped_ptr<ScreenOrientationDispatcher> dispatcher_;
@@ -109,4 +171,174 @@ TEST_F(ScreenOrientationDispatcherTest, ValidValues) {
listener_->screen_orientation());
}
+// Test that calling LockOrientation() followed by UnlockOrientation() cancel
+// the LockOrientation().
+TEST_F(ScreenOrientationDispatcherTest, CancelPending_Unlocking) {
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results;
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockPortraitPrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results));
+ dispatcher_->UnlockOrientation();
+
+ EXPECT_FALSE(callback_results.succeeded_);
+ EXPECT_TRUE(callback_results.failed_);
+ EXPECT_EQ(blink::WebLockOrientationCallback::ErrorTypeCanceled,
+ callback_results.error_);
+}
+
+// Test that calling LockOrientation() twice cancel the first LockOrientation().
+TEST_F(ScreenOrientationDispatcherTest, CancelPending_DoubleLock) {
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results;
+ // We create the object to prevent leaks but never actually use it.
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results2;
+
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockPortraitPrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results));
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockPortraitPrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results2));
+
+ EXPECT_FALSE(callback_results.succeeded_);
+ EXPECT_TRUE(callback_results.failed_);
+ EXPECT_EQ(blink::WebLockOrientationCallback::ErrorTypeCanceled,
+ callback_results.error_);
+}
+
+// Test that when a LockError message is received, the request is set as failed
+// with the correct values.
+TEST_F(ScreenOrientationDispatcherTest, LockRequest_Error) {
+ std::list<blink::WebLockOrientationCallback::ErrorType> errors;
+ errors.push_back(blink::WebLockOrientationCallback::ErrorTypeNotAvailable);
+ errors.push_back(
+ blink::WebLockOrientationCallback::ErrorTypeFullScreenRequired);
+ errors.push_back(blink::WebLockOrientationCallback::ErrorTypeCanceled);
+
+ for (std::list<blink::WebLockOrientationCallback::ErrorType>::const_iterator
+ it = errors.begin(); it != errors.end(); ++it) {
+ render_thread_->sink().ClearMessages();
+
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results;
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockPortraitPrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results));
+
+ int request_id = GetFirstLockRequestIdFromSink();
+ render_thread_->OnControlMessageReceived(
+ ScreenOrientationMsg_LockError(request_id, *it));
+
+ EXPECT_FALSE(callback_results.succeeded_);
+ EXPECT_TRUE(callback_results.failed_);
+ EXPECT_EQ(*it, callback_results.error_);
+ }
+}
+
+// Test that when a LockSuccess message is received, the request is set as
+// succeeded with the correct values.
+TEST_F(ScreenOrientationDispatcherTest, LockRequest_Success) {
+ struct ScreenOrientationInformation {
+ unsigned angle;
+ blink::WebScreenOrientationType type;
+ } orientations[] = {
+ { 0, blink::WebScreenOrientationPortraitPrimary },
+ { 0, blink::WebScreenOrientationLandscapePrimary },
+ { 90, blink::WebScreenOrientationPortraitSecondary },
+ { 90, blink::WebScreenOrientationLandscapePrimary }
+ };
+
+ int orientationsCount = 4;
+
+ for (int i = 0; i < orientationsCount; ++i) {
+ render_thread_->sink().ClearMessages();
+
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results;
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockPortraitPrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results));
+
+ int request_id = GetFirstLockRequestIdFromSink();
+ render_thread_->OnControlMessageReceived(
+ ScreenOrientationMsg_LockSuccess(request_id,
+ orientations[i].angle,
+ orientations[i].type));
+
+ EXPECT_TRUE(callback_results.succeeded_);
+ EXPECT_FALSE(callback_results.failed_);
+ EXPECT_EQ(orientations[i].angle, callback_results.angle_);
+ EXPECT_EQ(orientations[i].type, callback_results.orientation_);
+ }
+}
+
+// Test an edge case: a LockSuccess is received but it matches no pending
+// callback.
+TEST_F(ScreenOrientationDispatcherTest, SuccessForUnknownRequest) {
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results;
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockPortraitPrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results));
+
+ int request_id = GetFirstLockRequestIdFromSink();
+ render_thread_->OnControlMessageReceived(ScreenOrientationMsg_LockSuccess(
+ request_id + 1,
+ 90,
+ blink::WebScreenOrientationLandscapePrimary));
+
+ EXPECT_FALSE(callback_results.succeeded_);
+ EXPECT_FALSE(callback_results.failed_);
+}
+
+// Test an edge case: a LockError is received but it matches no pending
+// callback.
+TEST_F(ScreenOrientationDispatcherTest, ErrorForUnknownRequest) {
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results;
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockPortraitPrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results));
+
+ int request_id = GetFirstLockRequestIdFromSink();
+ render_thread_->OnControlMessageReceived(ScreenOrientationMsg_LockError(
+ request_id + 1,
+ blink::WebLockOrientationCallback::ErrorTypeCanceled));
+
+ EXPECT_FALSE(callback_results.succeeded_);
+ EXPECT_FALSE(callback_results.failed_);
+}
+
+// Test the following scenario:
+// - request1 is received by the dispatcher;
+// - request2 is received by the dispatcher;
+// - request1 is rejected;
+// - request1 success response is received.
+// Expected: request1 is still rejected, request2 has not been set as succeeded.
+TEST_F(ScreenOrientationDispatcherTest, RaceScenario) {
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results1;
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results2;
+
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockPortraitPrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results1));
+ int request_id1 = GetFirstLockRequestIdFromSink();
+
+ dispatcher_->LockOrientation(
+ blink::WebScreenOrientationLockLandscapePrimary,
+ MockLockOrientationCallback::CreateScoped(&callback_results2));
+
+ // callback_results1 must be rejected, tested in CancelPending_DoubleLock.
+
+ render_thread_->OnControlMessageReceived(ScreenOrientationMsg_LockSuccess(
+ request_id1,
+ 0,
+ blink::WebScreenOrientationPortraitPrimary));
+
+ // First request is still rejected.
+ EXPECT_FALSE(callback_results1.succeeded_);
+ EXPECT_TRUE(callback_results1.failed_);
+ EXPECT_EQ(blink::WebLockOrientationCallback::ErrorTypeCanceled,
+ callback_results1.error_);
+
+ // Second request is still pending.
+ EXPECT_FALSE(callback_results2.succeeded_);
+ EXPECT_FALSE(callback_results2.failed_);
+}
+
} // namespace content