1 // Copyright (c) 2017 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 "include/base/cef_callback.h"
6 #include "include/wrapper/cef_closure_task.h"
7
8 #include "tests/ceftests/routing_test_handler.h"
9 #include "tests/gtest/include/gtest/gtest.h"
10
11 namespace {
12
13 const char kTestUrl1[] = "https://tests/DisplayTestHandler.START";
14 const char kTestUrl2[] = "https://tests/DisplayTestHandler.NAVIGATE";
15 const char kTestMsg[] = "DisplayTestHandler.Status";
16
17 // Default OSR widget size.
18 const int kOsrWidth = 600;
19 const int kOsrHeight = 400;
20
21 class DisplayTestHandler : public RoutingTestHandler, public CefRenderHandler {
22 public:
DisplayTestHandler()23 DisplayTestHandler() : status_(START) {}
24
GetRenderHandler()25 CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; }
26
GetViewRect(CefRefPtr<CefBrowser> browser,CefRect & rect)27 void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override {
28 rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
29 }
30
GetScreenInfo(CefRefPtr<CefBrowser> browser,CefScreenInfo & screen_info)31 bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
32 CefScreenInfo& screen_info) override {
33 screen_info.rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
34 screen_info.available_rect = screen_info.rect;
35 return true;
36 }
37
OnPaint(CefRefPtr<CefBrowser> browser,CefRenderHandler::PaintElementType type,const CefRenderHandler::RectList & dirtyRects,const void * buffer,int width,int height)38 void OnPaint(CefRefPtr<CefBrowser> browser,
39 CefRenderHandler::PaintElementType type,
40 const CefRenderHandler::RectList& dirtyRects,
41 const void* buffer,
42 int width,
43 int height) override {
44 if (!got_paint_[status_]) {
45 got_paint_[status_].yes();
46
47 if (status_ == START) {
48 OnStartIfDone();
49 } else if (status_ == SHOW) {
50 CefPostTask(TID_UI,
51 base::BindOnce(&DisplayTestHandler::DestroyTest, this));
52 } else {
53 ADD_FAILURE();
54 }
55 }
56 }
57
RunTest()58 void RunTest() override {
59 // Add the resources that we will navigate to/from.
60 AddResource(kTestUrl1, GetPageContents("Page1", "START"), "text/html");
61 AddResource(kTestUrl2, GetPageContents("Page2", "NAVIGATE"), "text/html");
62
63 // Create the browser.
64 CreateOSRBrowser(kTestUrl1);
65
66 // Time out the test after a reasonable period of time.
67 SetTestTimeout(5000);
68 }
69
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)70 bool OnQuery(CefRefPtr<CefBrowser> browser,
71 CefRefPtr<CefFrame> frame,
72 int64 query_id,
73 const CefString& request,
74 bool persistent,
75 CefRefPtr<Callback> callback) override {
76 const std::string& request_str = request.ToString();
77 if (request_str.find(kTestMsg) == 0) {
78 const std::string& status = request_str.substr(sizeof(kTestMsg));
79 if (status == "START") {
80 got_start_msg_.yes();
81 OnStartIfDone();
82 } else if (status == "NAVIGATE") {
83 got_navigate_msg_.yes();
84 // Wait a bit to verify no OnPaint callback.
85 CefPostDelayedTask(
86 TID_UI, base::BindOnce(&DisplayTestHandler::OnNavigate, this), 250);
87 }
88 }
89 callback->Success("");
90 return true;
91 }
92
DestroyTest()93 void DestroyTest() override {
94 EXPECT_TRUE(got_paint_[START]);
95 EXPECT_FALSE(got_paint_[NAVIGATE]);
96 EXPECT_TRUE(got_paint_[SHOW]);
97
98 EXPECT_TRUE(got_start_msg_);
99 EXPECT_TRUE(got_navigate_msg_);
100
101 EXPECT_EQ(status_, SHOW);
102
103 RoutingTestHandler::DestroyTest();
104 }
105
106 private:
CreateOSRBrowser(const CefString & url)107 void CreateOSRBrowser(const CefString& url) {
108 CefWindowInfo windowInfo;
109 CefBrowserSettings settings;
110
111 #if defined(OS_WIN)
112 windowInfo.SetAsWindowless(GetDesktopWindow());
113 #else
114 windowInfo.SetAsWindowless(kNullWindowHandle);
115 #endif
116
117 CefBrowserHost::CreateBrowser(windowInfo, this, url, settings, nullptr,
118 nullptr);
119 }
120
GetPageContents(const std::string & name,const std::string & status)121 std::string GetPageContents(const std::string& name,
122 const std::string& status) {
123 return "<html><body>" + name + "<script>window.testQuery({request:'" +
124 std::string(kTestMsg) + ":" + status + "'});</script></body></html>";
125 }
126
OnStartIfDone()127 void OnStartIfDone() {
128 if (got_start_msg_ && got_paint_[START]) {
129 CefPostTask(TID_UI, base::BindOnce(&DisplayTestHandler::OnStart, this));
130 }
131 }
132
OnStart()133 void OnStart() {
134 EXPECT_EQ(status_, START);
135
136 // Hide the browser. OnPaint should not be called again until
137 // WasHidden(false) is explicitly called.
138 GetBrowser()->GetHost()->WasHidden(true);
139 status_ = NAVIGATE;
140
141 GetBrowser()->GetMainFrame()->LoadURL(kTestUrl2);
142 }
143
OnNavigate()144 void OnNavigate() {
145 EXPECT_EQ(status_, NAVIGATE);
146
147 // Show the browser.
148 status_ = SHOW;
149 GetBrowser()->GetHost()->WasHidden(false);
150
151 // Force a call to OnPaint.
152 GetBrowser()->GetHost()->Invalidate(PET_VIEW);
153 }
154
155 enum Status {
156 START,
157 NAVIGATE,
158 SHOW,
159 STATUS_COUNT,
160 };
161 Status status_;
162
163 TrackCallback got_paint_[STATUS_COUNT];
164 TrackCallback got_start_msg_;
165 TrackCallback got_navigate_msg_;
166
167 IMPLEMENT_REFCOUNTING(DisplayTestHandler);
168 };
169
170 } // namespace
171
172 // Test that browser visibility is not changed due to navigation.
TEST(OSRTest,NavigateWhileHidden)173 TEST(OSRTest, NavigateWhileHidden) {
174 CefRefPtr<DisplayTestHandler> handler = new DisplayTestHandler();
175 handler->ExecuteTest();
176 ReleaseAndWaitForDestructor(handler);
177 }
178
179 namespace {
180
181 const char kOsrPopupJSOtherClientMainUrl[] =
182 "http://www.tests-pjse.com/main.html";
183
184 class OsrPopupJSOtherClientTestHandler : public TestHandler,
185 public CefRenderHandler {
186 public:
OsrPopupJSOtherClientTestHandler(CefRefPtr<CefClient> other)187 OsrPopupJSOtherClientTestHandler(CefRefPtr<CefClient> other) {
188 other_ = other;
189 }
190
GetRenderHandler()191 virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override {
192 return this;
193 }
194
GetViewRect(CefRefPtr<CefBrowser> browser,CefRect & rect)195 virtual void GetViewRect(CefRefPtr<CefBrowser> browser,
196 CefRect& rect) override {
197 rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
198 }
199
OnPaint(CefRefPtr<CefBrowser> browser,PaintElementType type,const RectList & dirtyRects,const void * buffer,int width,int height)200 virtual void OnPaint(CefRefPtr<CefBrowser> browser,
201 PaintElementType type,
202 const RectList& dirtyRects,
203 const void* buffer,
204 int width,
205 int height) override {}
206
RunTest()207 void RunTest() override {
208 AddResource(kOsrPopupJSOtherClientMainUrl, "<html>Main</html>",
209 "text/html");
210
211 // Create the browser.
212 CreateOSRBrowser(kOsrPopupJSOtherClientMainUrl);
213
214 // Time out the test after a reasonable period of time.
215 SetTestTimeout();
216 }
217
OnBeforePopup(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & target_url,const CefString & target_frame_name,cef_window_open_disposition_t target_disposition,bool user_gesture,const CefPopupFeatures & popupFeatures,CefWindowInfo & windowInfo,CefRefPtr<CefClient> & client,CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> & extra_info,bool * no_javascript_access)218 bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
219 CefRefPtr<CefFrame> frame,
220 const CefString& target_url,
221 const CefString& target_frame_name,
222 cef_window_open_disposition_t target_disposition,
223 bool user_gesture,
224 const CefPopupFeatures& popupFeatures,
225 CefWindowInfo& windowInfo,
226 CefRefPtr<CefClient>& client,
227 CefBrowserSettings& settings,
228 CefRefPtr<CefDictionaryValue>& extra_info,
229 bool* no_javascript_access) override {
230 #if defined(OS_WIN)
231 windowInfo.SetAsWindowless(GetDesktopWindow());
232 #else
233 windowInfo.SetAsWindowless(kNullWindowHandle);
234 #endif
235
236 client = other_;
237
238 got_before_popup_.yes();
239 return false;
240 }
241
Close(CefRefPtr<CefBrowser> browser)242 void Close(CefRefPtr<CefBrowser> browser) {
243 browser->StopLoad();
244 CloseBrowser(browser, true);
245 }
246
OnAfterCreated(CefRefPtr<CefBrowser> browser)247 void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
248 TestHandler::OnAfterCreated(browser);
249 if (browser->IsPopup()) {
250 got_after_created_popup_.yes();
251 }
252 }
253
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)254 void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
255 bool isLoading,
256 bool canGoBack,
257 bool canGoForward) override {
258 if (isLoading)
259 return;
260
261 if (browser->IsPopup()) {
262 got_load_end_popup_.yes();
263 CefPostDelayedTask(
264 TID_UI,
265 base::BindOnce(&OsrPopupJSOtherClientTestHandler::Close, this,
266 browser),
267 100);
268 } else {
269 browser->GetMainFrame()->LoadURL("javascript:window.open('about:blank')");
270 }
271 }
272
OnBeforeClose(CefRefPtr<CefBrowser> browser)273 void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
274 TestHandler::OnBeforeClose(browser);
275 other_ = nullptr;
276 if (browser->IsPopup()) {
277 got_before_close_popup_.yes();
278 DestroyTest();
279 }
280 }
281
282 private:
CreateOSRBrowser(const CefString & url)283 void CreateOSRBrowser(const CefString& url) {
284 CefWindowInfo windowInfo;
285 CefBrowserSettings settings;
286
287 #if defined(OS_WIN)
288 windowInfo.SetAsWindowless(GetDesktopWindow());
289 #else
290 windowInfo.SetAsWindowless(kNullWindowHandle);
291 #endif
292
293 CefBrowserHost::CreateBrowser(windowInfo, this, url, settings, nullptr,
294 nullptr);
295 }
296
DestroyTest()297 void DestroyTest() override {
298 EXPECT_TRUE(got_after_created_popup_);
299 EXPECT_TRUE(got_load_end_popup_);
300 EXPECT_TRUE(got_before_close_popup_);
301 EXPECT_TRUE(got_before_popup_);
302 TestHandler::DestroyTest();
303 }
304
305 TrackCallback got_before_popup_;
306 TrackCallback got_after_created_popup_;
307 TrackCallback got_load_end_popup_;
308 TrackCallback got_before_close_popup_;
309 CefRefPtr<CefClient> other_;
310
311 IMPLEMENT_REFCOUNTING(OsrPopupJSOtherClientTestHandler);
312 };
313
314 class OsrPopupJSOtherCefClient : public CefClient,
315 public CefLoadHandler,
316 public CefLifeSpanHandler,
317 public CefRenderHandler {
318 public:
OsrPopupJSOtherCefClient()319 OsrPopupJSOtherCefClient() { handler_ = nullptr; }
320
SetHandler(CefRefPtr<OsrPopupJSOtherClientTestHandler> handler)321 void SetHandler(CefRefPtr<OsrPopupJSOtherClientTestHandler> handler) {
322 handler_ = handler;
323 }
324
GetLoadHandler()325 virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
326
GetRenderHandler()327 virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override {
328 return this;
329 }
330
GetLifeSpanHandler()331 virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override {
332 return this;
333 }
334
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)335 virtual void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
336 bool isLoading,
337 bool canGoBack,
338 bool canGoForward) override {
339 if (handler_) {
340 handler_->OnLoadingStateChange(browser, isLoading, canGoBack,
341 canGoForward);
342 }
343 }
344
OnAfterCreated(CefRefPtr<CefBrowser> browser)345 virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
346 handler_->OnAfterCreated(browser);
347 }
348
OnBeforeClose(CefRefPtr<CefBrowser> browser)349 virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
350 handler_->OnBeforeClose(browser);
351 handler_ = nullptr;
352 }
353
OnBeforePopup(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & target_url,const CefString & target_frame_name,cef_window_open_disposition_t target_disposition,bool user_gesture,const CefPopupFeatures & popupFeatures,CefWindowInfo & windowInfo,CefRefPtr<CefClient> & client,CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> & extra_info,bool * no_javascript_access)354 virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
355 CefRefPtr<CefFrame> frame,
356 const CefString& target_url,
357 const CefString& target_frame_name,
358 cef_window_open_disposition_t target_disposition,
359 bool user_gesture,
360 const CefPopupFeatures& popupFeatures,
361 CefWindowInfo& windowInfo,
362 CefRefPtr<CefClient>& client,
363 CefBrowserSettings& settings,
364 CefRefPtr<CefDictionaryValue>& extra_info,
365 bool* no_javascript_access) override {
366 return true;
367 }
368
GetViewRect(CefRefPtr<CefBrowser> browser,CefRect & rect)369 virtual void GetViewRect(CefRefPtr<CefBrowser> browser,
370 CefRect& rect) override {
371 rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
372 }
373
OnPaint(CefRefPtr<CefBrowser> browser,PaintElementType type,const RectList & dirtyRects,const void * buffer,int width,int height)374 virtual void OnPaint(CefRefPtr<CefBrowser> browser,
375 PaintElementType type,
376 const RectList& dirtyRects,
377 const void* buffer,
378 int width,
379 int height) override {}
380
381 private:
382 CefRefPtr<OsrPopupJSOtherClientTestHandler> handler_;
383
384 IMPLEMENT_REFCOUNTING(OsrPopupJSOtherCefClient);
385 };
386
387 } // namespace
388
389 // Test creation of an OSR-popup with another client.
TEST(OSRTest,OsrPopupJSOtherClient)390 TEST(OSRTest, OsrPopupJSOtherClient) {
391 CefRefPtr<OsrPopupJSOtherCefClient> client = new OsrPopupJSOtherCefClient();
392 CefRefPtr<OsrPopupJSOtherClientTestHandler> handler =
393 new OsrPopupJSOtherClientTestHandler(client);
394 client->SetHandler(handler);
395 handler->ExecuteTest();
396 ReleaseAndWaitForDestructor(handler);
397 }
398