Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / screen_orientation / screen_orientation_provider_android.cc
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 "content/browser/screen_orientation/screen_orientation_provider_android.h"
6
7 #include "content/browser/android/content_view_core_impl.h"
8 #include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/public/browser/render_view_host.h"
11 #include "content/public/browser/render_widget_host.h"
12 #include "jni/ScreenOrientationProvider_jni.h"
13 #include "third_party/WebKit/public/platform/WebLockOrientationError.h"
14 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
15
16 namespace content {
17
18 ScreenOrientationProviderAndroid::LockInformation::LockInformation(
19     int request_id, blink::WebScreenOrientationLockType lock)
20     : request_id(request_id), lock(lock) {}
21
22 ScreenOrientationProviderAndroid::ScreenOrientationProviderAndroid(
23     ScreenOrientationDispatcherHost* dispatcher,
24     WebContents* web_contents)
25     : ScreenOrientationProvider(),
26       WebContentsObserver(web_contents),
27       dispatcher_(dispatcher),
28       lock_applied_(false),
29       pending_lock_(NULL) {
30 }
31
32 ScreenOrientationProviderAndroid::~ScreenOrientationProviderAndroid() {
33   if (pending_lock_)
34     delete pending_lock_;
35 }
36
37 WebContentsImpl* ScreenOrientationProviderAndroid::web_contents_impl() {
38   return static_cast<WebContentsImpl*>(web_contents());
39 }
40
41 // static
42 bool ScreenOrientationProviderAndroid::Register(JNIEnv* env) {
43   return RegisterNativesImpl(env);
44 }
45
46 void ScreenOrientationProviderAndroid::LockOrientation(
47     int request_id,
48     blink::WebScreenOrientationLockType lock_orientation) {
49   ContentViewCoreImpl* cvc =
50       ContentViewCoreImpl::FromWebContents(web_contents());
51   bool fullscreen_required = cvc ? cvc->IsFullscreenRequiredForOrientationLock()
52                                  : true;
53
54   if (fullscreen_required &&
55       !web_contents_impl()->IsFullscreenForCurrentTab()) {
56     dispatcher_->NotifyLockError(
57         request_id,
58         blink::WebLockOrientationErrorFullScreenRequired);
59     return;
60   }
61
62   if (lock_orientation == blink::WebScreenOrientationLockNatural) {
63     lock_orientation = GetNaturalLockType();
64     if (lock_orientation == blink::WebScreenOrientationLockDefault) {
65       // We are in a broken state, let's pretend we got canceled.
66       dispatcher_->NotifyLockError(request_id,
67                                    blink::WebLockOrientationErrorCanceled);
68       return;
69     }
70   }
71
72   lock_applied_ = true;
73   Java_ScreenOrientationProvider_lockOrientation(
74       base::android::AttachCurrentThread(), lock_orientation);
75
76   // If two calls happen close to each other, Android will ignore the first.
77   if (pending_lock_) {
78     delete pending_lock_;
79     pending_lock_ = NULL;
80   }
81
82   // If the orientation we are locking to matches the current orientation, we
83   // should succeed immediately.
84   if (LockMatchesCurrentOrientation(lock_orientation)) {
85     dispatcher_->NotifyLockSuccess(request_id);
86     return;
87   }
88
89   pending_lock_ = new LockInformation(request_id, lock_orientation);
90 }
91
92 void ScreenOrientationProviderAndroid::UnlockOrientation() {
93   if (!lock_applied_)
94     return;
95
96   Java_ScreenOrientationProvider_unlockOrientation(
97       base::android::AttachCurrentThread());
98   lock_applied_ = false;
99 }
100
101 void ScreenOrientationProviderAndroid::OnOrientationChange() {
102   if (!pending_lock_)
103     return;
104
105   if (LockMatchesCurrentOrientation(pending_lock_->lock)) {
106     dispatcher_->NotifyLockSuccess(pending_lock_->request_id);
107     delete pending_lock_;
108     pending_lock_ = NULL;
109   }
110 }
111
112 void ScreenOrientationProviderAndroid::DidToggleFullscreenModeForTab(
113     bool entered_fullscreen) {
114   if (!lock_applied_)
115     return;
116
117   // If fullscreen is not required in order to lock orientation, don't unlock
118   // when fullscreen state changes.
119   ContentViewCoreImpl* cvc =
120       ContentViewCoreImpl::FromWebContents(web_contents());
121   if (cvc && !cvc->IsFullscreenRequiredForOrientationLock())
122     return;
123
124   DCHECK(!entered_fullscreen);
125   UnlockOrientation();
126 }
127
128 bool ScreenOrientationProviderAndroid::LockMatchesCurrentOrientation(
129     blink::WebScreenOrientationLockType lock_orientation) {
130   if (!web_contents()->GetRenderViewHost())
131     return false;
132
133   RenderWidgetHost* rwh = web_contents()->GetRenderViewHost();
134   blink::WebScreenInfo screen_info;
135   rwh->GetWebScreenInfo(&screen_info);
136
137   switch (lock_orientation) {
138   case blink::WebScreenOrientationLockPortraitPrimary:
139     return screen_info.orientationType ==
140         blink::WebScreenOrientationPortraitPrimary;
141   case blink::WebScreenOrientationLockPortraitSecondary:
142     return screen_info.orientationType ==
143         blink::WebScreenOrientationPortraitSecondary;
144   case blink::WebScreenOrientationLockLandscapePrimary:
145     return screen_info.orientationType ==
146         blink::WebScreenOrientationLandscapePrimary;
147   case blink::WebScreenOrientationLockLandscapeSecondary:
148     return screen_info.orientationType ==
149         blink::WebScreenOrientationLandscapeSecondary;
150   case blink::WebScreenOrientationLockLandscape:
151     return screen_info.orientationType ==
152         blink::WebScreenOrientationLandscapePrimary ||
153         screen_info.orientationType ==
154         blink::WebScreenOrientationLandscapeSecondary;
155   case blink::WebScreenOrientationLockPortrait:
156     return screen_info.orientationType ==
157         blink::WebScreenOrientationPortraitPrimary ||
158         screen_info.orientationType ==
159         blink::WebScreenOrientationPortraitSecondary;
160   case blink::WebScreenOrientationLockAny:
161     return true;
162   case blink::WebScreenOrientationLockNatural:
163   case blink::WebScreenOrientationLockDefault:
164     NOTREACHED();
165     return false;
166   }
167
168   NOTREACHED();
169   return false;
170 }
171
172 blink::WebScreenOrientationLockType
173 ScreenOrientationProviderAndroid::GetNaturalLockType() const {
174   if (!web_contents()->GetRenderViewHost())
175     return blink::WebScreenOrientationLockDefault;
176
177   RenderWidgetHost* rwh = web_contents()->GetRenderViewHost();
178   blink::WebScreenInfo screen_info;
179   rwh->GetWebScreenInfo(&screen_info);
180
181   switch (screen_info.orientationType) {
182   case blink::WebScreenOrientationPortraitPrimary:
183   case blink::WebScreenOrientationPortraitSecondary:
184     if (screen_info.orientationAngle == 0 ||
185         screen_info.orientationAngle == 180) {
186       return blink::WebScreenOrientationLockPortraitPrimary;
187     }
188     return blink::WebScreenOrientationLockLandscapePrimary;
189   case blink::WebScreenOrientationLandscapePrimary:
190   case blink::WebScreenOrientationLandscapeSecondary:
191     if (screen_info.orientationAngle == 0 ||
192         screen_info.orientationAngle == 180) {
193       return blink::WebScreenOrientationLockLandscapePrimary;
194     }
195     return blink::WebScreenOrientationLockPortraitPrimary;
196   case blink::WebScreenOrientationUndefined:
197     NOTREACHED();
198     return blink::WebScreenOrientationLockDefault;
199   }
200
201   NOTREACHED();
202   return blink::WebScreenOrientationLockDefault;
203 }
204
205 // static
206 void ScreenOrientationProviderAndroid::StartAccurateListening() {
207   Java_ScreenOrientationProvider_startAccurateListening(
208       base::android::AttachCurrentThread());
209 }
210
211 // static
212 void ScreenOrientationProviderAndroid::StopAccurateListening() {
213   Java_ScreenOrientationProvider_stopAccurateListening(
214       base::android::AttachCurrentThread());
215 }
216
217 // static
218 ScreenOrientationProvider* ScreenOrientationProvider::Create(
219     ScreenOrientationDispatcherHost* dispatcher,
220     WebContents* web_contents) {
221   return new ScreenOrientationProviderAndroid(dispatcher, web_contents);
222 }
223
224 } // namespace content