blob: de31b28f873d88fc6c27a0bdbaf74c4461548309 [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 "third_party/blink/renderer/modules/screen_orientation/screen_orientation.h"
#include <memory>
#include "base/stl_util.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.h"
#include "third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
// This code assumes that mojom::blink::ScreenOrientation values are included in
// device::mojom::blink::ScreenOrientationLockType.
STATIC_ASSERT_ENUM(
blink::mojom::blink::ScreenOrientation::kPortraitPrimary,
device::mojom::blink::ScreenOrientationLockType::PORTRAIT_PRIMARY);
STATIC_ASSERT_ENUM(
blink::mojom::blink::ScreenOrientation::kPortraitSecondary,
device::mojom::blink::ScreenOrientationLockType::PORTRAIT_SECONDARY);
STATIC_ASSERT_ENUM(
blink::mojom::blink::ScreenOrientation::kLandscapePrimary,
device::mojom::blink::ScreenOrientationLockType::LANDSCAPE_PRIMARY);
STATIC_ASSERT_ENUM(
blink::mojom::blink::ScreenOrientation::kLandscapeSecondary,
device::mojom::blink::ScreenOrientationLockType::LANDSCAPE_SECONDARY);
namespace blink {
struct ScreenOrientationInfo {
const AtomicString& name;
device::mojom::blink::ScreenOrientationLockType orientation;
};
static ScreenOrientationInfo* OrientationsMap(unsigned& length) {
DEFINE_STATIC_LOCAL(const AtomicString, portrait_primary,
("portrait-primary"));
DEFINE_STATIC_LOCAL(const AtomicString, portrait_secondary,
("portrait-secondary"));
DEFINE_STATIC_LOCAL(const AtomicString, landscape_primary,
("landscape-primary"));
DEFINE_STATIC_LOCAL(const AtomicString, landscape_secondary,
("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 orientation_map[] = {
{portrait_primary,
device::mojom::blink::ScreenOrientationLockType::PORTRAIT_PRIMARY},
{portrait_secondary,
device::mojom::blink::ScreenOrientationLockType::PORTRAIT_SECONDARY},
{landscape_primary,
device::mojom::blink::ScreenOrientationLockType::LANDSCAPE_PRIMARY},
{landscape_secondary,
device::mojom::blink::ScreenOrientationLockType::LANDSCAPE_SECONDARY},
{any, device::mojom::blink::ScreenOrientationLockType::ANY},
{portrait, device::mojom::blink::ScreenOrientationLockType::PORTRAIT},
{landscape, device::mojom::blink::ScreenOrientationLockType::LANDSCAPE},
{natural, device::mojom::blink::ScreenOrientationLockType::NATURAL}};
length = base::size(orientation_map);
return orientation_map;
}
const AtomicString& ScreenOrientation::OrientationTypeToString(
mojom::blink::ScreenOrientation orientation) {
unsigned length = 0;
ScreenOrientationInfo* orientation_map = OrientationsMap(length);
for (unsigned i = 0; i < length; ++i) {
if (static_cast<unsigned>(orientation) ==
static_cast<unsigned>(orientation_map[i].orientation))
return orientation_map[i].name;
}
NOTREACHED();
return g_null_atom;
}
static device::mojom::blink::ScreenOrientationLockType StringToOrientationLock(
const AtomicString& orientation_lock_string) {
unsigned length = 0;
ScreenOrientationInfo* orientation_map = OrientationsMap(length);
for (unsigned i = 0; i < length; ++i) {
if (orientation_map[i].name == orientation_lock_string)
return orientation_map[i].orientation;
}
NOTREACHED();
return device::mojom::blink::ScreenOrientationLockType::DEFAULT;
}
// static
ScreenOrientation* ScreenOrientation::Create(LocalDOMWindow* window) {
DCHECK(window);
ScreenOrientation* orientation =
MakeGarbageCollected<ScreenOrientation>(window);
orientation->Controller()->SetOrientation(orientation);
return orientation;
}
ScreenOrientation::ScreenOrientation(LocalDOMWindow* window)
: ExecutionContextClient(window),
type_(mojom::blink::ScreenOrientation::kUndefined),
angle_(0) {}
ScreenOrientation::~ScreenOrientation() = default;
const WTF::AtomicString& ScreenOrientation::InterfaceName() const {
return event_target_names::kScreenOrientation;
}
ExecutionContext* ScreenOrientation::GetExecutionContext() const {
return ExecutionContextClient::GetExecutionContext();
}
String ScreenOrientation::type() const {
return OrientationTypeToString(type_);
}
uint16_t ScreenOrientation::angle() const {
return angle_;
}
void ScreenOrientation::SetType(mojom::blink::ScreenOrientation type) {
type_ = type;
}
void ScreenOrientation::SetAngle(uint16_t angle) {
angle_ = angle;
}
ScriptPromise ScreenOrientation::lock(ScriptState* state,
const AtomicString& lock_string,
ExceptionState& exception_state) {
if (!state->ContextIsValid() || !Controller()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
"The object is no longer associated to a window.");
return ScriptPromise();
}
if (GetExecutionContext()->IsSandboxed(
network::mojom::blink::WebSandboxFlags::kOrientationLock)) {
exception_state.ThrowSecurityError(
"The window is sandboxed and lacks the "
"'allow-orientation-lock' flag.");
return ScriptPromise();
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(state);
ScriptPromise promise = resolver->Promise();
Controller()->lock(StringToOrientationLock(lock_string),
std::make_unique<LockOrientationCallback>(resolver));
return promise;
}
void ScreenOrientation::unlock() {
if (!Controller())
return;
Controller()->unlock();
}
ScreenOrientationController* ScreenOrientation::Controller() {
if (!GetExecutionContext())
return nullptr;
return ScreenOrientationController::From(
*To<LocalDOMWindow>(GetExecutionContext()));
}
void ScreenOrientation::Trace(Visitor* visitor) const {
EventTargetWithInlineData::Trace(visitor);
ExecutionContextClient::Trace(visitor);
}
} // namespace blink