blob: d83104ecca5e7c6db7dfe9b2287f402470a561c4 [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 "config.h"
#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/WebScreenOrientationType.h"
// This code assumes that WebScreenOrientationType values are included in WebScreenOrientationLockType.
#define COMPILE_ASSERT_MATCHING_ENUM(enum1, enum2) \
COMPILE_ASSERT(static_cast<unsigned>(blink::enum1) == static_cast<unsigned>(blink::enum2), mismatching_types)
COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationPortraitPrimary, WebScreenOrientationLockPortraitPrimary);
COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationPortraitSecondary, WebScreenOrientationLockPortraitSecondary);
COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationLandscapePrimary, WebScreenOrientationLockLandscapePrimary);
COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationLandscapeSecondary, WebScreenOrientationLockLandscapeSecondary);
namespace blink {
struct ScreenOrientationInfo {
const AtomicString& name;
unsigned orientation;
};
static ScreenOrientationInfo* orientationsMap(unsigned& length)
{
DEFINE_STATIC_LOCAL(const AtomicString, portraitPrimary, ("portrait-primary", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, portraitSecondary, ("portrait-secondary", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, landscapePrimary, ("landscape-primary", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, landscapeSecondary, ("landscape-secondary", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, any, ("any", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, portrait, ("portrait", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, landscape, ("landscape", AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, natural, ("natural", AtomicString::ConstructFromLiteral));
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);
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::executionContext() const
{
if (!m_frame)
return 0;
return m_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)
{
RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(state);
ScriptPromise promise = resolver->promise();
Document* document = m_frame ? m_frame->document() : 0;
if (!document || !controller()) {
RefPtrWillBeRawPtr<DOMException> exception = DOMException::create(InvalidStateError, "The object is no longer associated to a document.");
resolver->reject(exception);
return promise;
}
if (document->isSandboxed(SandboxOrientationLock)) {
RefPtrWillBeRawPtr<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 (!m_frame)
return 0;
return ScreenOrientationController::from(*m_frame);
}
void ScreenOrientation::trace(Visitor* visitor)
{
EventTargetWithInlineData::trace(visitor);
DOMWindowProperty::trace(visitor);
}
} // namespace blink