blob: 72940624841a48efb35075f7fe3d8031be3478cb [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/screen_orientation/screen_orientation_provider_android.h"
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "jni/ScreenOrientationProvider_jni.h"
#include "third_party/WebKit/public/platform/WebLockOrientationError.h"
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
namespace content {
ScreenOrientationProviderAndroid::LockInformation::LockInformation(
int request_id, blink::WebScreenOrientationLockType lock)
: request_id(request_id), lock(lock) {}
ScreenOrientationProviderAndroid::ScreenOrientationProviderAndroid(
ScreenOrientationDispatcherHost* dispatcher,
WebContents* web_contents)
: ScreenOrientationProvider(),
WebContentsObserver(web_contents),
dispatcher_(dispatcher),
lock_applied_(false),
pending_lock_(NULL) {
}
ScreenOrientationProviderAndroid::~ScreenOrientationProviderAndroid() {
if (pending_lock_)
delete pending_lock_;
}
WebContentsImpl* ScreenOrientationProviderAndroid::web_contents_impl() {
return static_cast<WebContentsImpl*>(web_contents());
}
// static
bool ScreenOrientationProviderAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
void ScreenOrientationProviderAndroid::LockOrientation(
int request_id,
blink::WebScreenOrientationLockType lock_orientation) {
ContentViewCoreImpl* cvc =
ContentViewCoreImpl::FromWebContents(web_contents());
bool fullscreen_required = cvc ? cvc->IsFullscreenRequiredForOrientationLock()
: true;
if (fullscreen_required &&
!web_contents_impl()->IsFullscreenForCurrentTab()) {
dispatcher_->NotifyLockError(
request_id,
blink::WebLockOrientationErrorFullScreenRequired);
return;
}
if (lock_orientation == blink::WebScreenOrientationLockNatural) {
lock_orientation = GetNaturalLockType();
if (lock_orientation == blink::WebScreenOrientationLockDefault) {
// We are in a broken state, let's pretend we got canceled.
dispatcher_->NotifyLockError(request_id,
blink::WebLockOrientationErrorCanceled);
return;
}
}
lock_applied_ = true;
Java_ScreenOrientationProvider_lockOrientation(
base::android::AttachCurrentThread(), lock_orientation);
// If two calls happen close to each other, Android will ignore the first.
if (pending_lock_) {
delete pending_lock_;
pending_lock_ = NULL;
}
// If the orientation we are locking to matches the current orientation, we
// should succeed immediately.
if (LockMatchesCurrentOrientation(lock_orientation)) {
dispatcher_->NotifyLockSuccess(request_id);
return;
}
pending_lock_ = new LockInformation(request_id, lock_orientation);
}
void ScreenOrientationProviderAndroid::UnlockOrientation() {
if (!lock_applied_)
return;
Java_ScreenOrientationProvider_unlockOrientation(
base::android::AttachCurrentThread());
lock_applied_ = false;
}
void ScreenOrientationProviderAndroid::OnOrientationChange() {
if (!pending_lock_)
return;
if (LockMatchesCurrentOrientation(pending_lock_->lock)) {
dispatcher_->NotifyLockSuccess(pending_lock_->request_id);
delete pending_lock_;
pending_lock_ = NULL;
}
}
void ScreenOrientationProviderAndroid::DidToggleFullscreenModeForTab(
bool entered_fullscreen) {
if (!lock_applied_)
return;
// If fullscreen is not required in order to lock orientation, don't unlock
// when fullscreen state changes.
ContentViewCoreImpl* cvc =
ContentViewCoreImpl::FromWebContents(web_contents());
if (cvc && !cvc->IsFullscreenRequiredForOrientationLock())
return;
DCHECK(!entered_fullscreen);
UnlockOrientation();
}
bool ScreenOrientationProviderAndroid::LockMatchesCurrentOrientation(
blink::WebScreenOrientationLockType lock_orientation) {
if (!web_contents()->GetRenderViewHost())
return false;
RenderWidgetHost* rwh = web_contents()->GetRenderViewHost();
blink::WebScreenInfo screen_info;
rwh->GetWebScreenInfo(&screen_info);
switch (lock_orientation) {
case blink::WebScreenOrientationLockPortraitPrimary:
return screen_info.orientationType ==
blink::WebScreenOrientationPortraitPrimary;
case blink::WebScreenOrientationLockPortraitSecondary:
return screen_info.orientationType ==
blink::WebScreenOrientationPortraitSecondary;
case blink::WebScreenOrientationLockLandscapePrimary:
return screen_info.orientationType ==
blink::WebScreenOrientationLandscapePrimary;
case blink::WebScreenOrientationLockLandscapeSecondary:
return screen_info.orientationType ==
blink::WebScreenOrientationLandscapeSecondary;
case blink::WebScreenOrientationLockLandscape:
return screen_info.orientationType ==
blink::WebScreenOrientationLandscapePrimary ||
screen_info.orientationType ==
blink::WebScreenOrientationLandscapeSecondary;
case blink::WebScreenOrientationLockPortrait:
return screen_info.orientationType ==
blink::WebScreenOrientationPortraitPrimary ||
screen_info.orientationType ==
blink::WebScreenOrientationPortraitSecondary;
case blink::WebScreenOrientationLockAny:
return true;
case blink::WebScreenOrientationLockNatural:
case blink::WebScreenOrientationLockDefault:
NOTREACHED();
return false;
}
NOTREACHED();
return false;
}
blink::WebScreenOrientationLockType
ScreenOrientationProviderAndroid::GetNaturalLockType() const {
if (!web_contents()->GetRenderViewHost())
return blink::WebScreenOrientationLockDefault;
RenderWidgetHost* rwh = web_contents()->GetRenderViewHost();
blink::WebScreenInfo screen_info;
rwh->GetWebScreenInfo(&screen_info);
switch (screen_info.orientationType) {
case blink::WebScreenOrientationPortraitPrimary:
case blink::WebScreenOrientationPortraitSecondary:
if (screen_info.orientationAngle == 0 ||
screen_info.orientationAngle == 180) {
return blink::WebScreenOrientationLockPortraitPrimary;
}
return blink::WebScreenOrientationLockLandscapePrimary;
case blink::WebScreenOrientationLandscapePrimary:
case blink::WebScreenOrientationLandscapeSecondary:
if (screen_info.orientationAngle == 0 ||
screen_info.orientationAngle == 180) {
return blink::WebScreenOrientationLockLandscapePrimary;
}
return blink::WebScreenOrientationLockPortraitPrimary;
case blink::WebScreenOrientationUndefined:
NOTREACHED();
return blink::WebScreenOrientationLockDefault;
}
NOTREACHED();
return blink::WebScreenOrientationLockDefault;
}
// static
void ScreenOrientationProviderAndroid::StartAccurateListening() {
Java_ScreenOrientationProvider_startAccurateListening(
base::android::AttachCurrentThread());
}
// static
void ScreenOrientationProviderAndroid::StopAccurateListening() {
Java_ScreenOrientationProvider_stopAccurateListening(
base::android::AttachCurrentThread());
}
// static
ScreenOrientationProvider* ScreenOrientationProvider::Create(
ScreenOrientationDispatcherHost* dispatcher,
WebContents* web_contents) {
return new ScreenOrientationProviderAndroid(dispatcher, web_contents);
}
} // namespace content