Home | History | Annotate | Download | only in screen_orientation
      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