blob: fff6c22fc7df64efb911e6d18cb21da09f68e29a [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 "modules/screen_orientation/ScreenOrientation.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/dom/DOMException.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/frame/LocalFrame.h"
#include "modules/EventTargetModules.h"
#include "modules/screen_orientation/LockOrientationCallback.h"
#include "modules/screen_orientation/ScreenOrientationController.h"
#include "public/platform/modules/screen_orientation/WebScreenOrientationType.h"
// This code assumes that WebScreenOrientationType values are included in
// WebScreenOrientationLockType.
#define STATIC_ASSERT_ENUM(a, b) \
static_assert(static_cast<int>(a) == static_cast<int>(b), \
"mismatching enum: " #a)
STATIC_ASSERT_ENUM(blink::WebScreenOrientationPortraitPrimary,
blink::WebScreenOrientationLockPortraitPrimary);
STATIC_ASSERT_ENUM(blink::WebScreenOrientationPortraitSecondary,
blink::WebScreenOrientationLockPortraitSecondary);
STATIC_ASSERT_ENUM(blink::WebScreenOrientationLandscapePrimary,
blink::WebScreenOrientationLockLandscapePrimary);
STATIC_ASSERT_ENUM(blink::WebScreenOrientationLandscapeSecondary,
blink::WebScreenOrientationLockLandscapeSecondary);
namespace blink {
struct ScreenOrientationInfo {
const AtomicString& name;
unsigned orientation;
};
static ScreenOrientationInfo* orientationsMap(unsigned& length) {
DEFINE_STATIC_LOCAL(const AtomicString, portraitPrimary,
("portrait-primary"));
DEFINE_STATIC_LOCAL(const AtomicString, portraitSecondary,
("portrait-secondary"));
DEFINE_STATIC_LOCAL(const AtomicString, landscapePrimary,
("landscape-primary"));
DEFINE_STATIC_LOCAL(const AtomicString, landscapeSecondary,
("landscape-secondary"));
DEFINE_STATIC_LOCAL(const AtomicString, any, ("any"));
DEFINE_STATIC_LOCAL(const AtomicString, portrait, ("portrait"));
DEFINE_STATIC_LOCAL(const AtomicString, landscape, ("landscape"));
DEFINE_STATIC_LOCAL(const AtomicString, natural, ("natural"));
static ScreenOrientationInfo orientationMap[] = {
{portraitPrimary, WebScreenOrientationLockPortraitPrimary},
{portraitSecondary, WebScreenOrientationLockPortraitSecondary},
{landscapePrimary, WebScreenOrientationLockLandscapePrimary},
{landscapeSecondary, WebScreenOrientationLockLandscapeSecondary},
{any, WebScreenOrientationLockAny},
{portrait, WebScreenOrientationLockPortrait},
{landscape, WebScreenOrientationLockLandscape},
{natural, WebScreenOrientationLockNatural}};
length = WTF_ARRAY_LENGTH(orientationMap);
return orientationMap;
}
const AtomicString& ScreenOrientation::orientationTypeToString(
WebScreenOrientationType orientation) {
unsigned length = 0;
ScreenOrientationInfo* orientationMap = orientationsMap(length);
for (unsigned i = 0; i < length; ++i) {
if (static_cast<unsigned>(orientation) == orientationMap[i].orientation)
return orientationMap[i].name;
}
ASSERT_NOT_REACHED();
return nullAtom;
}
static WebScreenOrientationLockType stringToOrientationLock(
const AtomicString& orientationLockString) {
unsigned length = 0;
ScreenOrientationInfo* orientationMap = orientationsMap(length);
for (unsigned i = 0; i < length; ++i) {
if (orientationMap[i].name == orientationLockString)
return static_cast<WebScreenOrientationLockType>(
orientationMap[i].orientation);
}
ASSERT_NOT_REACHED();
return WebScreenOrientationLockDefault;
}
// static
ScreenOrientation* ScreenOrientation::create(LocalFrame* frame) {
ASSERT(frame);
// Check if the ScreenOrientationController is supported for the
// frame. It will not be for all LocalFrames, or the frame may
// have been detached.
if (!ScreenOrientationController::from(*frame))
return nullptr;
ScreenOrientation* orientation = new ScreenOrientation(frame);
ASSERT(orientation->controller());
// FIXME: ideally, we would like to provide the ScreenOrientationController
// the case where it is not defined but for the moment, it is eagerly
// created when the LocalFrame is created so we shouldn't be in that
// situation.
// In order to create the ScreenOrientationController lazily, we would need
// to be able to access WebFrameClient from modules/.
orientation->controller()->setOrientation(orientation);
return orientation;
}
ScreenOrientation::ScreenOrientation(LocalFrame* frame)
: DOMWindowProperty(frame),
m_type(WebScreenOrientationUndefined),
m_angle(0) {}
ScreenOrientation::~ScreenOrientation() {}
const WTF::AtomicString& ScreenOrientation::interfaceName() const {
return EventTargetNames::ScreenOrientation;
}
ExecutionContext* ScreenOrientation::getExecutionContext() const {
if (!frame())
return 0;
return frame()->document();
}
String ScreenOrientation::type() const {
return orientationTypeToString(m_type);
}
unsigned short ScreenOrientation::angle() const {
return m_angle;
}
void ScreenOrientation::setType(WebScreenOrientationType type) {
m_type = type;
}
void ScreenOrientation::setAngle(unsigned short angle) {
m_angle = angle;
}
ScriptPromise ScreenOrientation::lock(ScriptState* state,
const AtomicString& lockString) {
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(state);
ScriptPromise promise = resolver->promise();
Document* document = frame() ? frame()->document() : 0;
if (!document || !controller()) {
DOMException* exception = DOMException::create(
InvalidStateError, "The object is no longer associated to a document.");
resolver->reject(exception);
return promise;
}
if (document->isSandboxed(SandboxOrientationLock)) {
DOMException* exception =
DOMException::create(SecurityError,
"The document is sandboxed and lacks the "
"'allow-orientation-lock' flag.");
resolver->reject(exception);
return promise;
}
controller()->lock(stringToOrientationLock(lockString),
new LockOrientationCallback(resolver));
return promise;
}
void ScreenOrientation::unlock() {
if (!controller())
return;
controller()->unlock();
}
ScreenOrientationController* ScreenOrientation::controller() {
if (!frame())
return 0;
return ScreenOrientationController::from(*frame());
}
DEFINE_TRACE(ScreenOrientation) {
EventTargetWithInlineData::trace(visitor);
DOMWindowProperty::trace(visitor);
}
} // namespace blink