1 // Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "tests/ceftests/views/test_window_delegate.h"
6
7 #include "include/cef_command_line.h"
8 #include "include/views/cef_window.h"
9 #include "include/views/cef_window_delegate.h"
10 #include "include/wrapper/cef_closure_task.h"
11 #include "tests/ceftests/thread_helper.h"
12 #include "tests/gtest/include/gtest/gtest.h"
13
14 #if defined(OS_WIN)
15 #include <windows.h>
16 #endif
17
18 namespace {
19
20 // Test timeout in MS.
21 const int kTestTimeout = 5000;
22
23 } // namespace
24
25 // static
26 const int TestWindowDelegate::kWSize = 400;
27
28 // static
RunTest(CefRefPtr<CefWaitableEvent> event,const Config & config)29 void TestWindowDelegate::RunTest(CefRefPtr<CefWaitableEvent> event,
30 const Config& config) {
31 #if defined(OS_WIN)
32 RECT rect = {0, 0, config.window_size, config.window_size};
33 if (!config.frameless) {
34 // The size value is for the client area. Calculate the whole window size
35 // based on the default frame window style.
36 AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
37 false /* has_menu */);
38 }
39 CefSize window_size = CefSize(rect.right - rect.left, rect.bottom - rect.top);
40 #else
41 CefSize window_size = CefSize(config.window_size, config.window_size);
42 #endif
43
44 CefWindow::CreateTopLevelWindow(
45 new TestWindowDelegate(event, config, window_size));
46 }
47
OnWindowCreated(CefRefPtr<CefWindow> window)48 void TestWindowDelegate::OnWindowCreated(CefRefPtr<CefWindow> window) {
49 EXPECT_FALSE(window_);
50 window_ = window;
51
52 EXPECT_TRUE(window->IsValid());
53 EXPECT_FALSE(window->IsClosed());
54
55 EXPECT_FALSE(window->IsVisible());
56 EXPECT_FALSE(window->IsDrawn());
57
58 EXPECT_FALSE(window->IsActive());
59 EXPECT_FALSE(window->IsAlwaysOnTop());
60 EXPECT_FALSE(window->IsMaximized());
61 EXPECT_FALSE(window->IsMinimized());
62 EXPECT_FALSE(window->IsFullscreen());
63
64 const char* title = "ViewsTest";
65 window->SetTitle(title);
66 EXPECT_STREQ(title, window->GetTitle().ToString().c_str());
67
68 EXPECT_FALSE(window->GetWindowIcon().get());
69 EXPECT_FALSE(window->GetWindowAppIcon().get());
70
71 auto display = window->GetDisplay();
72 EXPECT_TRUE(display.get());
73
74 // Size will come from GetGetInitialBounds() or GetPreferredSize() on
75 // initial Window creation.
76 EXPECT_TRUE(got_get_initial_bounds_);
77 if (config_.window_origin.IsEmpty())
78 EXPECT_TRUE(got_get_preferred_size_);
79 else
80 EXPECT_FALSE(got_get_preferred_size_);
81
82 CefRect client_bounds = window->GetBounds();
83 if (!config_.window_origin.IsEmpty()) {
84 EXPECT_EQ(config_.window_origin.x, client_bounds.x);
85 EXPECT_EQ(config_.window_origin.y, client_bounds.y);
86 } else {
87 // Default origin is the upper-left corner of the display's work area.
88 auto work_area = display->GetWorkArea();
89 EXPECT_EQ(work_area.x, client_bounds.x);
90 EXPECT_EQ(work_area.y, client_bounds.y);
91 }
92
93 if (config_.frameless) {
94 EXPECT_EQ(config_.window_size, client_bounds.width);
95 EXPECT_EQ(config_.window_size, client_bounds.height);
96 } else {
97 // Client area bounds calculation might have off-by-one errors on Windows
98 // due to non-client frame size being calculated internally in pixels and
99 // then converted to DIPs. See http://crbug.com/602692.
100 EXPECT_TRUE(abs(client_bounds.width - window_size_.width) <= 1);
101 EXPECT_TRUE(abs(client_bounds.height - window_size_.height) <= 1);
102 }
103
104 // Run the callback.
105 if (!config_.on_window_created.is_null())
106 config_.on_window_created.Run(window);
107
108 if (config_.close_window) {
109 // Close the window asynchronously.
110 CefPostTask(TID_UI, base::Bind(&TestWindowDelegate::OnCloseWindow, this));
111 } else if (!CefCommandLine::GetGlobalCommandLine()->HasSwitch(
112 "disable-test-timeout")) {
113 // Timeout the test after a reasonable delay. Use a WeakPtr so that the
114 // delayed task doesn't keep this object alive.
115 CefPostDelayedTask(TID_UI,
116 base::Bind(&TestWindowDelegate::OnTimeoutWindow,
117 weak_ptr_factory_.GetWeakPtr()),
118 kTestTimeout);
119 }
120 }
121
OnWindowDestroyed(CefRefPtr<CefWindow> window)122 void TestWindowDelegate::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
123 EXPECT_TRUE(window->IsSame(window_));
124
125 EXPECT_TRUE(window->IsValid());
126 EXPECT_TRUE(window->IsClosed());
127 EXPECT_FALSE(window->IsVisible());
128 EXPECT_FALSE(window->IsDrawn());
129
130 // Run the callback.
131 if (!config_.on_window_destroyed.is_null())
132 config_.on_window_destroyed.Run(window);
133
134 window_ = nullptr;
135
136 // Don't execute the timeout callback.
137 weak_ptr_factory_.InvalidateWeakPtrs();
138 }
139
IsFrameless(CefRefPtr<CefWindow> window)140 bool TestWindowDelegate::IsFrameless(CefRefPtr<CefWindow> window) {
141 return config_.frameless;
142 }
143
GetInitialBounds(CefRefPtr<CefWindow> window)144 CefRect TestWindowDelegate::GetInitialBounds(CefRefPtr<CefWindow> window) {
145 got_get_initial_bounds_ = true;
146 if (!config_.window_origin.IsEmpty()) {
147 return CefRect(config_.window_origin.x, config_.window_origin.y,
148 window_size_.width, window_size_.height);
149 }
150
151 // Call GetPreferredSize().
152 return CefRect();
153 }
154
GetPreferredSize(CefRefPtr<CefView> view)155 CefSize TestWindowDelegate::GetPreferredSize(CefRefPtr<CefView> view) {
156 got_get_preferred_size_ = true;
157 return window_size_;
158 }
159
OnAccelerator(CefRefPtr<CefWindow> window,int command_id)160 bool TestWindowDelegate::OnAccelerator(CefRefPtr<CefWindow> window,
161 int command_id) {
162 if (!config_.on_accelerator.is_null())
163 return config_.on_accelerator.Run(window_, command_id);
164 return false;
165 }
166
OnKeyEvent(CefRefPtr<CefWindow> window,const CefKeyEvent & event)167 bool TestWindowDelegate::OnKeyEvent(CefRefPtr<CefWindow> window,
168 const CefKeyEvent& event) {
169 if (!config_.on_key_event.is_null())
170 return config_.on_key_event.Run(window_, event);
171 return false;
172 }
173
TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,const Config & config,const CefSize & window_size)174 TestWindowDelegate::TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,
175 const Config& config,
176 const CefSize& window_size)
177 : event_(event),
178 config_(config),
179 window_size_(window_size),
180 weak_ptr_factory_(this) {}
181
~TestWindowDelegate()182 TestWindowDelegate::~TestWindowDelegate() {
183 // Complete the test (signal the event) asynchronously so objects on the call
184 // stack have a chance to unwind.
185 CefPostTask(TID_UI, base::Bind(SignalEvent, event_));
186 }
187
OnCloseWindow()188 void TestWindowDelegate::OnCloseWindow() {
189 if (!window_)
190 return;
191
192 EXPECT_TRUE(window_->IsValid());
193 EXPECT_FALSE(window_->IsClosed());
194
195 // Close() may clear |window_| so keep a reference.
196 CefRefPtr<CefWindow> window = window_;
197 window->Close();
198
199 EXPECT_TRUE(window->IsValid());
200 EXPECT_TRUE(window->IsClosed());
201 }
202
OnTimeoutWindow()203 void TestWindowDelegate::OnTimeoutWindow() {
204 EXPECT_TRUE(false) << "Test timed out after " << kTestTimeout << "ms";
205 OnCloseWindow();
206 }
207