• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,std::unique_ptr<Config> config)29 void TestWindowDelegate::RunTest(CefRefPtr<CefWaitableEvent> event,
30                                  std::unique_ptr<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, std::move(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     std::move(config_->on_window_created).Run(window);
107 
108   if (config_->close_window) {
109     // Close the window asynchronously.
110     CefPostTask(TID_UI,
111                 base::BindOnce(&TestWindowDelegate::OnCloseWindow, this));
112   } else if (!CefCommandLine::GetGlobalCommandLine()->HasSwitch(
113                  "disable-test-timeout")) {
114     // Timeout the test after a reasonable delay. Use a WeakPtr so that the
115     // delayed task doesn't keep this object alive.
116     CefPostDelayedTask(TID_UI,
117                        base::BindOnce(&TestWindowDelegate::OnTimeoutWindow,
118                                       weak_ptr_factory_.GetWeakPtr()),
119                        kTestTimeout);
120   }
121 }
122 
OnWindowDestroyed(CefRefPtr<CefWindow> window)123 void TestWindowDelegate::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
124   EXPECT_TRUE(window->IsSame(window_));
125 
126   EXPECT_TRUE(window->IsValid());
127   EXPECT_TRUE(window->IsClosed());
128   EXPECT_FALSE(window->IsVisible());
129   EXPECT_FALSE(window->IsDrawn());
130 
131   // Run the callback.
132   if (!config_->on_window_destroyed.is_null())
133     std::move(config_->on_window_destroyed).Run(window);
134 
135   window_ = nullptr;
136 
137   // Don't execute the timeout callback.
138   weak_ptr_factory_.InvalidateWeakPtrs();
139 }
140 
IsFrameless(CefRefPtr<CefWindow> window)141 bool TestWindowDelegate::IsFrameless(CefRefPtr<CefWindow> window) {
142   return config_->frameless;
143 }
144 
GetInitialBounds(CefRefPtr<CefWindow> window)145 CefRect TestWindowDelegate::GetInitialBounds(CefRefPtr<CefWindow> window) {
146   got_get_initial_bounds_ = true;
147   if (!config_->window_origin.IsEmpty()) {
148     return CefRect(config_->window_origin.x, config_->window_origin.y,
149                    window_size_.width, window_size_.height);
150   }
151 
152   // Call GetPreferredSize().
153   return CefRect();
154 }
155 
GetPreferredSize(CefRefPtr<CefView> view)156 CefSize TestWindowDelegate::GetPreferredSize(CefRefPtr<CefView> view) {
157   got_get_preferred_size_ = true;
158   return window_size_;
159 }
160 
OnAccelerator(CefRefPtr<CefWindow> window,int command_id)161 bool TestWindowDelegate::OnAccelerator(CefRefPtr<CefWindow> window,
162                                        int command_id) {
163   if (!config_->on_accelerator.is_null())
164     return config_->on_accelerator.Run(window_, command_id);
165   return false;
166 }
167 
OnKeyEvent(CefRefPtr<CefWindow> window,const CefKeyEvent & event)168 bool TestWindowDelegate::OnKeyEvent(CefRefPtr<CefWindow> window,
169                                     const CefKeyEvent& event) {
170   if (!config_->on_key_event.is_null())
171     return config_->on_key_event.Run(window_, event);
172   return false;
173 }
174 
TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,std::unique_ptr<Config> config,const CefSize & window_size)175 TestWindowDelegate::TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,
176                                        std::unique_ptr<Config> config,
177                                        const CefSize& window_size)
178     : event_(event),
179       config_(std::move(config)),
180       window_size_(window_size),
181       weak_ptr_factory_(this) {}
182 
~TestWindowDelegate()183 TestWindowDelegate::~TestWindowDelegate() {
184   // Complete the test (signal the event) asynchronously so objects on the call
185   // stack have a chance to unwind.
186   CefPostTask(TID_UI, base::BindOnce(SignalEvent, event_));
187 }
188 
OnCloseWindow()189 void TestWindowDelegate::OnCloseWindow() {
190   if (!window_)
191     return;
192 
193   EXPECT_TRUE(window_->IsValid());
194   EXPECT_FALSE(window_->IsClosed());
195 
196   // Close() may clear |window_| so keep a reference.
197   CefRefPtr<CefWindow> window = window_;
198   window->Close();
199 
200   EXPECT_TRUE(window->IsValid());
201   EXPECT_TRUE(window->IsClosed());
202 }
203 
OnTimeoutWindow()204 void TestWindowDelegate::OnTimeoutWindow() {
205   EXPECT_TRUE(false) << "Test timed out after " << kTestTimeout << "ms";
206   OnCloseWindow();
207 }
208