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 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 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 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 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 104 ScreenOrientation::ScreenOrientation(LocalFrame* frame) 105 : DOMWindowProperty(frame) 106 , m_type(WebScreenOrientationUndefined) 107 , m_angle(0) 108 { 109 } 110 111 ScreenOrientation::~ScreenOrientation() 112 { 113 } 114 115 const WTF::AtomicString& ScreenOrientation::interfaceName() const 116 { 117 return EventTargetNames::ScreenOrientation; 118 } 119 120 ExecutionContext* ScreenOrientation::executionContext() const 121 { 122 if (!m_frame) 123 return 0; 124 return m_frame->document(); 125 } 126 127 String ScreenOrientation::type() const 128 { 129 return orientationTypeToString(m_type); 130 } 131 132 unsigned short ScreenOrientation::angle() const 133 { 134 return m_angle; 135 } 136 137 void ScreenOrientation::setType(WebScreenOrientationType type) 138 { 139 m_type = type; 140 } 141 142 void ScreenOrientation::setAngle(unsigned short angle) 143 { 144 m_angle = angle; 145 } 146 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 170 void ScreenOrientation::unlock() 171 { 172 if (!controller()) 173 return; 174 175 controller()->unlock(); 176 } 177 178 ScreenOrientationController* ScreenOrientation::controller() 179 { 180 if (!m_frame) 181 return 0; 182 183 return ScreenOrientationController::from(*m_frame); 184 } 185 186 void ScreenOrientation::trace(Visitor* visitor) 187 { 188 EventTargetWithInlineData::trace(visitor); 189 DOMWindowProperty::trace(visitor); 190 } 191 192 } // namespace blink 193