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 <stdlib.h>
6
7#include "base/command_line.h"
8#include "content/browser/renderer_host/render_widget_host_impl.h"
9#include "content/common/view_messages.h"
10#include "content/public/browser/render_widget_host.h"
11#include "content/public/browser/render_widget_host_view.h"
12#include "content/public/browser/web_contents.h"
13#include "content/public/common/content_switches.h"
14#include "content/public/test/browser_test_utils.h"
15#include "content/public/test/content_browser_test.h"
16#include "content/public/test/content_browser_test_utils.h"
17#include "content/public/test/test_navigation_observer.h"
18#include "content/public/test/test_utils.h"
19#include "content/shell/browser/shell.h"
20#include "content/shell/common/shell_switches.h"
21#include "third_party/WebKit/public/platform/WebScreenInfo.h"
22#include "ui/compositor/compositor_switches.h"
23
24#if defined(OS_WIN)
25#include "base/win/windows_version.h"
26#endif // OS_WIN
27
28namespace content {
29
30class ScreenOrientationBrowserTest : public ContentBrowserTest  {
31 public:
32  ScreenOrientationBrowserTest() {
33  }
34
35  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
36    command_line->AppendSwitch(
37        switches::kEnableExperimentalWebPlatformFeatures);
38  }
39
40  virtual void SetUp() OVERRIDE {
41    // Painting has to happen otherwise the Resize messages will be added on top
42    // of each other without properly ack-painting which will fail and crash.
43    UseSoftwareCompositing();
44
45    ContentBrowserTest::SetUp();
46  }
47
48 protected:
49  void SendFakeScreenOrientation(unsigned angle, const std::string& strType) {
50    RenderWidgetHost* rwh = shell()->web_contents()->GetRenderWidgetHostView()
51        ->GetRenderWidgetHost();
52    blink::WebScreenInfo screen_info;
53    rwh->GetWebScreenInfo(&screen_info);
54    screen_info.orientationAngle = angle;
55
56    blink::WebScreenOrientationType type = blink::WebScreenOrientationUndefined;
57    if (strType == "portrait-primary") {
58      type = blink::WebScreenOrientationPortraitPrimary;
59    } else if (strType == "portrait-secondary") {
60      type = blink::WebScreenOrientationPortraitSecondary;
61    } else if (strType == "landscape-primary") {
62      type = blink::WebScreenOrientationLandscapePrimary;
63    } else if (strType == "landscape-secondary") {
64      type = blink::WebScreenOrientationLandscapeSecondary;
65    }
66    ASSERT_NE(blink::WebScreenOrientationUndefined, type);
67    screen_info.orientationType = type;
68
69    ViewMsg_Resize_Params params;
70    params.screen_info = screen_info;
71    params.new_size = gfx::Size(0, 0);
72    params.physical_backing_size = gfx::Size(300, 300);
73    params.top_controls_layout_height = 0.f;
74    params.resizer_rect = gfx::Rect();
75    params.is_fullscreen = false;
76    rwh->Send(new ViewMsg_Resize(rwh->GetRoutingID(), params));
77  }
78
79  int GetOrientationAngle() {
80    int angle;
81    ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
82                             "screen.orientation.angle")->GetAsInteger(&angle);
83    return angle;
84  }
85
86  std::string GetOrientationType() {
87    std::string type;
88    ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
89                             "screen.orientation.type")->GetAsString(&type);
90    return type;
91  }
92
93  bool ScreenOrientationSupported() {
94    bool support;
95    ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
96                             "'orientation' in screen")->GetAsBoolean(&support);
97    return support;
98  }
99
100  bool WindowOrientationSupported() {
101    bool support;
102    ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
103                             "'orientation' in window")->GetAsBoolean(&support);
104    return support;
105  }
106
107  int GetWindowOrientationAngle() {
108    int angle;
109    ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
110                             "window.orientation")->GetAsInteger(&angle);
111    return angle;
112  }
113
114 private:
115  DISALLOW_COPY_AND_ASSIGN(ScreenOrientationBrowserTest);
116};
117
118// This test doesn't work on MacOS X but the reason is mostly because it is not
119// used Aura. It could be set as !defined(OS_MACOSX) but the rule below will
120// actually support MacOS X if and when it switches to Aura.
121#if defined(USE_AURA) || defined(OS_ANDROID)
122IN_PROC_BROWSER_TEST_F(ScreenOrientationBrowserTest, ScreenOrientationChange) {
123  std::string types[] = { "portrait-primary",
124                          "portrait-secondary",
125                          "landscape-primary",
126                          "landscape-secondary" };
127  GURL test_url = GetTestUrl("screen_orientation",
128                             "screen_orientation_screenorientationchange.html");
129
130  TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
131  shell()->LoadURL(test_url);
132  navigation_observer.Wait();
133#if USE_AURA
134  WaitForResizeComplete(shell()->web_contents());
135#endif // USE_AURA
136
137#if defined(OS_WIN)
138  // Screen Orientation is currently disabled on Windows 8.
139  // This test will break, requiring an update when the API will be enabled.
140  if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_WIN8) {
141    EXPECT_EQ(false, ScreenOrientationSupported());
142    return;
143  }
144#endif // defined(OS_WIN)
145
146  int angle = GetOrientationAngle();
147
148  for (int i = 0; i < 4; ++i) {
149    angle = (angle + 90) % 360;
150    SendFakeScreenOrientation(angle, types[i]);
151
152    TestNavigationObserver navigation_observer(shell()->web_contents());
153    navigation_observer.Wait();
154    EXPECT_EQ(angle, GetOrientationAngle());
155    EXPECT_EQ(types[i], GetOrientationType());
156  }
157}
158#endif // defined(USE_AURA) || defined(OS_ANDROID)
159
160IN_PROC_BROWSER_TEST_F(ScreenOrientationBrowserTest, WindowOrientationChange) {
161  GURL test_url = GetTestUrl("screen_orientation",
162                             "screen_orientation_windoworientationchange.html");
163
164  TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
165  shell()->LoadURL(test_url);
166  navigation_observer.Wait();
167#if USE_AURA
168  WaitForResizeComplete(shell()->web_contents());
169#endif // USE_AURA
170
171  if (!WindowOrientationSupported())
172    return;
173
174  int angle = GetWindowOrientationAngle();
175
176  for (int i = 0; i < 4; ++i) {
177    angle = (angle + 90) % 360;
178    SendFakeScreenOrientation(angle, "portrait-primary");
179
180    TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
181    navigation_observer.Wait();
182    EXPECT_EQ(angle == 270 ? -90 : angle, GetWindowOrientationAngle());
183  }
184}
185
186// Chromium Android does not support fullscreen
187IN_PROC_BROWSER_TEST_F(ScreenOrientationBrowserTest, LockSmoke) {
188  GURL test_url = GetTestUrl("screen_orientation",
189                             "screen_orientation_lock_smoke.html");
190
191  TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
192  shell()->LoadURL(test_url);
193
194#if defined(OS_WIN)
195  // Screen Orientation is currently disabled on Windows 8.
196  // This test will break, requiring an update when the API will be enabled.
197  if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_WIN8) {
198    EXPECT_EQ(false, ScreenOrientationSupported());
199    return;
200  }
201#endif // defined(OS_WIN)
202
203  navigation_observer.Wait();
204#if USE_AURA
205  WaitForResizeComplete(shell()->web_contents());
206#endif // USE_AURA
207
208  std::string expected =
209#if defined(OS_ANDROID)
210      "SecurityError"; // WebContents need to be fullscreen.
211#else
212      "NotSupportedError"; // Locking isn't supported.
213#endif
214
215  EXPECT_EQ(expected, shell()->web_contents()->GetLastCommittedURL().ref());
216}
217
218} // namespace content
219