1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "modules/screen_orientation/ScreenOrientation.h"
7
8 #include "bindings/core/v8/ScriptPromise.h"
9 #include "bindings/core/v8/ScriptPromiseResolver.h"
10 #include "core/dom/DOMException.h"
11 #include "core/dom/Document.h"
12 #include "core/dom/ExceptionCode.h"
13 #include "core/frame/LocalFrame.h"
14 #include "modules/EventTargetModules.h"
15 #include "modules/screen_orientation/LockOrientationCallback.h"
16 #include "modules/screen_orientation/ScreenOrientationController.h"
17 #include "public/platform/WebScreenOrientationType.h"
18
19 // This code assumes that WebScreenOrientationType values are included in WebScreenOrientationLockType.
20 #define COMPILE_ASSERT_MATCHING_ENUM(enum1, enum2) \
21 COMPILE_ASSERT(static_cast<unsigned>(blink::enum1) == static_cast<unsigned>(blink::enum2), mismatching_types)
22 COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationPortraitPrimary, WebScreenOrientationLockPortraitPrimary);
23 COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationPortraitSecondary, WebScreenOrientationLockPortraitSecondary);
24 COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationLandscapePrimary, WebScreenOrientationLockLandscapePrimary);
25 COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationLandscapeSecondary, WebScreenOrientationLockLandscapeSecondary);
26
27 namespace blink {
28
29 struct ScreenOrientationInfo {
30 const AtomicString& name;
31 unsigned orientation;
32 };
33
orientationsMap(unsigned & length)34 static ScreenOrientationInfo* orientationsMap(unsigned& length)
35 {
36 DEFINE_STATIC_LOCAL(const AtomicString, portraitPrimary, ("portrait-primary", AtomicString::ConstructFromLiteral));
37 DEFINE_STATIC_LOCAL(const AtomicString, portraitSecondary, ("portrait-secondary", AtomicString::ConstructFromLiteral));
38 DEFINE_STATIC_LOCAL(const AtomicString, landscapePrimary, ("landscape-primary", AtomicString::ConstructFromLiteral));
39 DEFINE_STATIC_LOCAL(const AtomicString, landscapeSecondary, ("landscape-secondary", AtomicString::ConstructFromLiteral));
40 DEFINE_STATIC_LOCAL(const AtomicString, any, ("any", AtomicString::ConstructFromLiteral));
41 DEFINE_STATIC_LOCAL(const AtomicString, portrait, ("portrait", AtomicString::ConstructFromLiteral));
42 DEFINE_STATIC_LOCAL(const AtomicString, landscape, ("landscape", AtomicString::ConstructFromLiteral));
43 DEFINE_STATIC_LOCAL(const AtomicString, natural, ("natural", AtomicString::ConstructFromLiteral));
44
45 static ScreenOrientationInfo orientationMap[] = {
46 { portraitPrimary, WebScreenOrientationLockPortraitPrimary },
47 { portraitSecondary, WebScreenOrientationLockPortraitSecondary },
48 { landscapePrimary, WebScreenOrientationLockLandscapePrimary },
49 { landscapeSecondary, WebScreenOrientationLockLandscapeSecondary },
50 { any, WebScreenOrientationLockAny },
51 { portrait, WebScreenOrientationLockPortrait },
52 { landscape, WebScreenOrientationLockLandscape },
53 { natural, WebScreenOrientationLockNatural }
54 };
55 length = WTF_ARRAY_LENGTH(orientationMap);
56
57 return orientationMap;
58 }
59
orientationTypeToString(WebScreenOrientationType orientation)60 const AtomicString& ScreenOrientation::orientationTypeToString(WebScreenOrientationType orientation)
61 {
62 unsigned length = 0;
63 ScreenOrientationInfo* orientationMap = orientationsMap(length);
64 for (unsigned i = 0; i < length; ++i) {
65 if (static_cast<unsigned>(orientation) == orientationMap[i].orientation)
66 return orientationMap[i].name;
67 }
68
69 ASSERT_NOT_REACHED();
70 return nullAtom;
71 }
72
stringToOrientationLock(const AtomicString & orientationLockString)73 static WebScreenOrientationLockType stringToOrientationLock(const AtomicString& orientationLockString)
74 {
75 unsigned length = 0;
76 ScreenOrientationInfo* orientationMap = orientationsMap(length);
77 for (unsigned i = 0; i < length; ++i) {
78 if (orientationMap[i].name == orientationLockString)
79 return static_cast<WebScreenOrientationLockType>(orientationMap[i].orientation);
80 }
81
82 ASSERT_NOT_REACHED();
83 return WebScreenOrientationLockDefault;
84 }
85
86 // static
create(LocalFrame * frame)87 ScreenOrientation* ScreenOrientation::create(LocalFrame* frame)
88 {
89 ASSERT(frame);
90
91 ScreenOrientation* orientation = adoptRefCountedGarbageCollectedWillBeNoop(new ScreenOrientation(frame));
92 ASSERT(orientation->controller());
93 // FIXME: ideally, we would like to provide the ScreenOrientationController
94 // the case where it is not defined but for the moment, it is eagerly
95 // created when the LocalFrame is created so we shouldn't be in that
96 // situation.
97 // In order to create the ScreenOrientationController lazily, we would need
98 // to be able to access WebFrameClient from modules/.
99
100 orientation->controller()->setOrientation(orientation);
101 return orientation;
102 }
103
ScreenOrientation(LocalFrame * frame)104 ScreenOrientation::ScreenOrientation(LocalFrame* frame)
105 : DOMWindowProperty(frame)
106 , m_type(WebScreenOrientationUndefined)
107 , m_angle(0)
108 {
109 }
110
~ScreenOrientation()111 ScreenOrientation::~ScreenOrientation()
112 {
113 }
114
interfaceName() const115 const WTF::AtomicString& ScreenOrientation::interfaceName() const
116 {
117 return EventTargetNames::ScreenOrientation;
118 }
119
executionContext() const120 ExecutionContext* ScreenOrientation::executionContext() const
121 {
122 if (!m_frame)
123 return 0;
124 return m_frame->document();
125 }
126
type() const127 String ScreenOrientation::type() const
128 {
129 return orientationTypeToString(m_type);
130 }
131
angle() const132 unsigned short ScreenOrientation::angle() const
133 {
134 return m_angle;
135 }
136
setType(WebScreenOrientationType type)137 void ScreenOrientation::setType(WebScreenOrientationType type)
138 {
139 m_type = type;
140 }
141
setAngle(unsigned short angle)142 void ScreenOrientation::setAngle(unsigned short angle)
143 {
144 m_angle = angle;
145 }
146
lock(ScriptState * state,const AtomicString & lockString)147 ScriptPromise ScreenOrientation::lock(ScriptState* state, const AtomicString& lockString)
148 {
149 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(state);
150 ScriptPromise promise = resolver->promise();
151
152 Document* document = m_frame ? m_frame->document() : 0;
153
154 if (!document || !controller()) {
155 RefPtrWillBeRawPtr<DOMException> exception = DOMException::create(InvalidStateError, "The object is no longer associated to a document.");
156 resolver->reject(exception);
157 return promise;
158 }
159
160 if (document->isSandboxed(SandboxOrientationLock)) {
161 RefPtrWillBeRawPtr<DOMException> exception = DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-orientation-lock' flag.");
162 resolver->reject(exception);
163 return promise;
164 }
165
166 controller()->lock(stringToOrientationLock(lockString), new LockOrientationCallback(resolver));
167 return promise;
168 }
169
unlock()170 void ScreenOrientation::unlock()
171 {
172 if (!controller())
173 return;
174
175 controller()->unlock();
176 }
177
controller()178 ScreenOrientationController* ScreenOrientation::controller()
179 {
180 if (!m_frame)
181 return 0;
182
183 return ScreenOrientationController::from(*m_frame);
184 }
185
trace(Visitor * visitor)186 void ScreenOrientation::trace(Visitor* visitor)
187 {
188 EventTargetWithInlineData::trace(visitor);
189 DOMWindowProperty::trace(visitor);
190 }
191
192 } // namespace blink
193