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/ScreenOrientationController.h" 7 8 #include "core/dom/Document.h" 9 #include "core/frame/LocalDOMWindow.h" 10 #include "core/frame/FrameView.h" 11 #include "core/frame/LocalFrame.h" 12 #include "core/frame/Screen.h" 13 #include "core/page/Page.h" 14 #include "platform/LayoutTestSupport.h" 15 #include "platform/PlatformScreen.h" 16 #include "public/platform/WebScreenOrientationClient.h" 17 18 namespace WebCore { 19 20 ScreenOrientationController::~ScreenOrientationController() 21 { 22 } 23 24 void ScreenOrientationController::persistentHostHasBeenDestroyed() 25 { 26 // Unregister lifecycle observation once page is being torn down. 27 observeContext(0); 28 } 29 30 void ScreenOrientationController::provideTo(LocalFrame& frame, blink::WebScreenOrientationClient* client) 31 { 32 ScreenOrientationController* controller = new ScreenOrientationController(frame, client); 33 WillBeHeapSupplement<LocalFrame>::provideTo(frame, supplementName(), adoptPtrWillBeNoop(controller)); 34 } 35 36 ScreenOrientationController& ScreenOrientationController::from(LocalFrame& frame) 37 { 38 return *static_cast<ScreenOrientationController*>(WillBeHeapSupplement<LocalFrame>::from(frame, supplementName())); 39 } 40 41 ScreenOrientationController::ScreenOrientationController(LocalFrame& frame, blink::WebScreenOrientationClient* client) 42 : PageLifecycleObserver(frame.page()) 43 , m_overrideOrientation(blink::WebScreenOrientationUndefined) 44 , m_client(client) 45 , m_frame(frame) 46 { 47 } 48 49 const char* ScreenOrientationController::supplementName() 50 { 51 return "ScreenOrientationController"; 52 } 53 54 // Compute the screen orientation using the orientation angle and the screen width / height. 55 blink::WebScreenOrientationType ScreenOrientationController::computeOrientation(FrameView* view) 56 { 57 // Bypass orientation detection in layout tests to get consistent results. 58 // FIXME: The screen dimension should be fixed when running the layout tests to avoid such 59 // issues. 60 if (isRunningLayoutTest()) 61 return blink::WebScreenOrientationPortraitPrimary; 62 63 FloatRect rect = screenRect(view); 64 uint16_t rotation = screenOrientationAngle(view); 65 bool isTallDisplay = rotation % 180 ? rect.height() < rect.width() : rect.height() > rect.width(); 66 switch (rotation) { 67 case 0: 68 return isTallDisplay ? blink::WebScreenOrientationPortraitPrimary : blink::WebScreenOrientationLandscapePrimary; 69 case 90: 70 return isTallDisplay ? blink::WebScreenOrientationLandscapePrimary : blink::WebScreenOrientationPortraitSecondary; 71 case 180: 72 return isTallDisplay ? blink::WebScreenOrientationPortraitSecondary : blink::WebScreenOrientationLandscapeSecondary; 73 case 270: 74 return isTallDisplay ? blink::WebScreenOrientationLandscapeSecondary : blink::WebScreenOrientationPortraitPrimary; 75 default: 76 ASSERT_NOT_REACHED(); 77 return blink::WebScreenOrientationPortraitPrimary; 78 } 79 } 80 81 void ScreenOrientationController::pageVisibilityChanged() 82 { 83 if (page() && page()->visibilityState() == PageVisibilityStateVisible) { 84 blink::WebScreenOrientationType oldOrientation = m_overrideOrientation; 85 m_overrideOrientation = blink::WebScreenOrientationUndefined; 86 // FIXME: sendOrientationChangeEvent() currently send an event all the 87 // children of the frame, so it should only be called on the frame on 88 // top of the tree. We would need the embedder to call 89 // sendOrientationChangeEvent on every WebFrame part of a WebView to be 90 // able to remove this. 91 if (m_frame == m_frame.localFrameRoot() && oldOrientation != orientation()) 92 m_frame.sendOrientationChangeEvent(); 93 } else if (m_overrideOrientation == blink::WebScreenOrientationUndefined) { 94 // The page is no longer visible, store the last know screen orientation 95 // so that we keep returning this orientation until the page becomes 96 // visible again. 97 m_overrideOrientation = orientation(); 98 } 99 } 100 101 blink::WebScreenOrientationType ScreenOrientationController::orientation() const 102 { 103 if (m_overrideOrientation != blink::WebScreenOrientationUndefined) { 104 // The page is not visible, keep returning the last known screen orientation. 105 ASSERT(!page() || page()->visibilityState() != PageVisibilityStateVisible); 106 return m_overrideOrientation; 107 } 108 109 blink::WebScreenOrientationType orientationType = screenOrientationType(m_frame.view()); 110 if (orientationType == blink::WebScreenOrientationUndefined) { 111 // The embedder could not provide us with an orientation, deduce it ourselves. 112 orientationType = computeOrientation(m_frame.view()); 113 } 114 ASSERT(orientationType != blink::WebScreenOrientationUndefined); 115 return orientationType; 116 } 117 118 void ScreenOrientationController::lockOrientation(blink::WebScreenOrientationLockType orientation, blink::WebLockOrientationCallback* callback) 119 { 120 if (!m_client) { 121 return; 122 } 123 124 m_client->lockOrientation(orientation, callback); 125 } 126 127 void ScreenOrientationController::unlockOrientation() 128 { 129 if (!m_client) { 130 return; 131 } 132 133 m_client->unlockOrientation(); 134 } 135 136 } // namespace WebCore 137