1 // Copyright (c) 2013 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 <list>
6
7 #include "include/base/cef_callback.h"
8 #include "include/wrapper/cef_closure_task.h"
9 #include "tests/ceftests/routing_test_handler.h"
10 #include "tests/ceftests/test_handler.h"
11 #include "tests/gtest/include/gtest/gtest.h"
12
13 namespace {
14
15 // How it works:
16 // 1. Load kTitleUrl1 (title should be kTitleStr1)
17 // 2. Load kTitleUrl2 (title should be kTitleStr2)
18 // 3. History back to kTitleUrl1 (title should be kTitleStr1)
19 // 4. History forward to kTitleUrl2 (title should be kTitleStr2)
20 // 5. Set title via JavaScript (title should be kTitleStr3)
21
22 const char kTitleUrl1[] = "http://tests-title/nav1.html";
23 const char kTitleUrl2[] = "http://tests-title/nav2.html";
24 const char kTitleStr1[] = "Title 1";
25 const char kTitleStr2[] = "Title 2";
26 const char kTitleStr3[] = "Title 3";
27
28 // Browser side.
29 class TitleTestHandler : public TestHandler {
30 public:
TitleTestHandler()31 TitleTestHandler()
32 : step_(0), got_title_change_(false), got_loading_state_change_(false) {}
33
RunTest()34 void RunTest() override {
35 // Add the resources that we will navigate to/from.
36 AddResource(kTitleUrl1,
37 "<html><head><title>" + std::string(kTitleStr1) +
38 "</title></head>Nav1</html>",
39 "text/html");
40 AddResource(kTitleUrl2,
41 "<html><head><title>" + std::string(kTitleStr2) +
42 "</title></head>Nav2" +
43 "<script>function setTitle() { window.document.title = '" +
44 std::string(kTitleStr3) + "'; }</script>" + "</html>",
45 "text/html");
46
47 // Create the browser.
48 CreateBrowser(kTitleUrl1);
49
50 // Time out the test after a reasonable period of time.
51 SetTestTimeout();
52 }
53
OnTitleChange(CefRefPtr<CefBrowser> browser,const CefString & title)54 void OnTitleChange(CefRefPtr<CefBrowser> browser,
55 const CefString& title) override {
56 // Ignore the 2nd OnTitleChange call which arrives after navigation
57 // completion.
58 if (got_title_change_)
59 return;
60
61 std::string title_str = title;
62 if (step_ == 0 || step_ == 2) {
63 EXPECT_STREQ(kTitleStr1, title_str.c_str());
64 } else if (step_ == 1 || step_ == 3) {
65 EXPECT_STREQ(kTitleStr2, title_str.c_str());
66 } else if (step_ == 4) {
67 EXPECT_STREQ(kTitleStr3, title_str.c_str());
68 }
69
70 got_title_[step_].yes();
71
72 if (step_ == 4) {
73 DestroyTest();
74 } else {
75 got_title_change_ = true;
76 NextIfReady(browser);
77 }
78 }
79
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)80 void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
81 bool isLoading,
82 bool canGoBack,
83 bool canGoForward) override {
84 if (isLoading)
85 return;
86
87 // Call NextIfReady asynchronously because an additional call to
88 // OnTitleChange will be triggered later in the current call stack due to
89 // navigation completion and we want that call to arrive before execution of
90 // NextIfReady.
91 got_loading_state_change_ = true;
92 CefPostTask(TID_UI,
93 base::BindOnce(&TitleTestHandler::NextIfReady, this, browser));
94 }
95
96 private:
NextIfReady(CefRefPtr<CefBrowser> browser)97 void NextIfReady(CefRefPtr<CefBrowser> browser) {
98 if (!got_title_change_ || !got_loading_state_change_)
99 return;
100
101 got_title_change_ = false;
102 got_loading_state_change_ = false;
103
104 switch (step_++) {
105 case 0:
106 browser->GetMainFrame()->LoadURL(kTitleUrl2);
107 break;
108 case 1:
109 browser->GoBack();
110 break;
111 case 2:
112 browser->GoForward();
113 break;
114 case 3:
115 browser->GetMainFrame()->ExecuteJavaScript("setTitle()", kTitleUrl2, 0);
116 break;
117 default:
118 EXPECT_TRUE(false); // Not reached.
119 }
120 }
121
DestroyTest()122 void DestroyTest() override {
123 for (int i = 0; i < 5; ++i)
124 EXPECT_TRUE(got_title_[i]) << "step " << i;
125
126 TestHandler::DestroyTest();
127 }
128
129 int step_;
130
131 bool got_title_change_;
132 bool got_loading_state_change_;
133
134 TrackCallback got_title_[5];
135
136 IMPLEMENT_REFCOUNTING(TitleTestHandler);
137 };
138
139 } // namespace
140
141 // Test title notifications.
TEST(DisplayTest,Title)142 TEST(DisplayTest, Title) {
143 CefRefPtr<TitleTestHandler> handler = new TitleTestHandler();
144 handler->ExecuteTest();
145 ReleaseAndWaitForDestructor(handler);
146 }
147
148 namespace {
149
150 const char kAutoResizeUrl[] = "http://tests-display/auto-resize.html";
151
152 class AutoResizeTestHandler : public RoutingTestHandler {
153 public:
AutoResizeTestHandler()154 AutoResizeTestHandler() {}
155
RunTest()156 void RunTest() override {
157 // Add the resources that we will navigate to/from.
158 AddResource(kAutoResizeUrl,
159 "<html><head><style>"
160 "body {overflow:hidden;margin:0px;padding:0px;}"
161 "</style></head><body><div id=a>Content</div></body></html>",
162 "text/html");
163
164 // Create the browser.
165 CreateBrowser(kAutoResizeUrl);
166
167 // Time out the test after a reasonable period of time.
168 SetTestTimeout();
169 }
170
OnAfterCreated(CefRefPtr<CefBrowser> browser)171 void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
172 RoutingTestHandler::OnAfterCreated(browser);
173 browser->GetHost()->SetAutoResizeEnabled(true, CefSize(10, 10),
174 CefSize(500, 500));
175 }
176
OnAutoResize(CefRefPtr<CefBrowser> browser,const CefSize & new_size)177 bool OnAutoResize(CefRefPtr<CefBrowser> browser,
178 const CefSize& new_size) override {
179 if (new_size.width == 1064 && new_size.height == 576) {
180 // Ignore this initial resize that may or may not occur.
181 } else if (!got_auto_resize1_) {
182 got_auto_resize1_.yes();
183 EXPECT_EQ(50, new_size.width);
184 EXPECT_EQ(18, new_size.height);
185
186 // Trigger a resize.
187 browser->GetMainFrame()->ExecuteJavaScript(
188 "document.getElementById('a').innerText='New Content';",
189 kAutoResizeUrl, 0);
190 } else if (!got_auto_resize2_) {
191 got_auto_resize2_.yes();
192 EXPECT_EQ(50, new_size.width);
193 EXPECT_EQ(36, new_size.height);
194
195 // Disable resize notifications.
196 browser->GetHost()->SetAutoResizeEnabled(false, CefSize(), CefSize());
197
198 // There should be no more resize notifications. End the test after a
199 // short delay.
200 browser->GetMainFrame()->ExecuteJavaScript(
201 "document.getElementById('a').innerText='New Content Again';"
202 "var interval = setInterval(function() {"
203 "window.testQuery({request:'done'});clearInterval(interval);}, 50);",
204 kAutoResizeUrl, 0);
205 } else {
206 EXPECT_TRUE(false); // Not reached.
207 }
208 return true;
209 }
210
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)211 bool OnQuery(CefRefPtr<CefBrowser> browser,
212 CefRefPtr<CefFrame> frame,
213 int64 query_id,
214 const CefString& request,
215 bool persistent,
216 CefRefPtr<Callback> callback) override {
217 EXPECT_STREQ("done", request.ToString().c_str());
218 EXPECT_FALSE(got_done_message_);
219 got_done_message_.yes();
220 DestroyTest();
221 return true;
222 }
223
DestroyTest()224 void DestroyTest() override {
225 EXPECT_TRUE(got_auto_resize1_);
226 EXPECT_TRUE(got_auto_resize2_);
227 EXPECT_TRUE(got_done_message_);
228 TestHandler::DestroyTest();
229 }
230
231 private:
232 TrackCallback got_auto_resize1_;
233 TrackCallback got_auto_resize2_;
234 TrackCallback got_done_message_;
235
236 IMPLEMENT_REFCOUNTING(AutoResizeTestHandler);
237 };
238
239 } // namespace
240
241 // Test OnAutoResize notification.
TEST(DisplayTest,AutoResize)242 TEST(DisplayTest, AutoResize) {
243 CefRefPtr<AutoResizeTestHandler> handler = new AutoResizeTestHandler();
244 handler->ExecuteTest();
245 ReleaseAndWaitForDestructor(handler);
246 }
247
248 namespace {
249
250 // Browser side.
251 class ConsoleTestHandler : public TestHandler {
252 public:
253 struct TestConfig {
254 // Use something other than 1 as |line| for testing.
TestConfig__anonfadd5f3b0311::ConsoleTestHandler::TestConfig255 explicit TestConfig(cef_log_severity_t message_level)
256 : level(message_level),
257 message("'Test Message'"),
258 expected_message("Test Message"),
259 source("http://tests-console-message/level.html"),
260 line(42) {}
261
262 cef_log_severity_t level;
263 std::string message;
264 std::string expected_message;
265 std::string source;
266 int line;
267 std::string function;
268 };
269
ConsoleTestHandler(const TestConfig & config)270 ConsoleTestHandler(const TestConfig& config) : config_(config) {}
271
RunTest()272 void RunTest() override {
273 // Add the resources that will be used to print to console.
274 AddResource(
275 config_.source,
276 CreateResourceContent(config_.message, config_.function, config_.line),
277 "text/html");
278
279 // Create the browser.
280 CreateBrowser(config_.source);
281
282 // Time out the test after a reasonable period of time.
283 SetTestTimeout();
284 }
285
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)286 void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
287 bool isLoading,
288 bool canGoBack,
289 bool canGoForward) override {
290 if (isLoading)
291 return;
292
293 // Print console message after loading.
294 browser->GetMainFrame()->ExecuteJavaScript("printMessage()", config_.source,
295 0);
296 }
297
OnConsoleMessage(CefRefPtr<CefBrowser> browser,cef_log_severity_t level,const CefString & message,const CefString & source,int line)298 bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
299 cef_log_severity_t level,
300 const CefString& message,
301 const CefString& source,
302 int line) override {
303 EXPECT_EQ(config_.level, level);
304 EXPECT_EQ(config_.expected_message, message.ToString());
305 EXPECT_EQ(config_.source, source.ToString());
306 EXPECT_EQ(config_.line, line);
307
308 TestHandler::DestroyTest();
309
310 return false;
311 }
312
313 private:
CreateResourceContent(const CefString & message,const CefString & function,int line)314 std::string CreateResourceContent(const CefString& message,
315 const CefString& function,
316 int line) {
317 std::string content = "<html><script>function printMessage() { ";
318 for (int i = 1; i < line; ++i) {
319 // Add additional lines to test the |line| argument in |OnConsoleMessage|.
320 content += ";\n";
321 }
322 content += "console." + function.ToString() + "(" + message.ToString() +
323 "); }</script></html>";
324
325 return content;
326 }
327
328 TestConfig config_;
329
330 IMPLEMENT_REFCOUNTING(ConsoleTestHandler);
331 };
332
333 } // namespace
334
TEST(DisplayTest,OnConsoleMessageDebug)335 TEST(DisplayTest, OnConsoleMessageDebug) {
336 ConsoleTestHandler::TestConfig config(LOGSEVERITY_DEBUG);
337 config.function = "debug";
338
339 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
340 handler->ExecuteTest();
341 ReleaseAndWaitForDestructor(handler);
342 }
343
TEST(DisplayTest,OnConsoleMessageCount)344 TEST(DisplayTest, OnConsoleMessageCount) {
345 ConsoleTestHandler::TestConfig config(LOGSEVERITY_DEBUG);
346 config.function = "count";
347 config.expected_message = "Test Message: 1";
348
349 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
350 handler->ExecuteTest();
351 ReleaseAndWaitForDestructor(handler);
352 }
353
TEST(DisplayTest,OnConsoleMessageTimeEnd)354 TEST(DisplayTest, OnConsoleMessageTimeEnd) {
355 ConsoleTestHandler::TestConfig config(LOGSEVERITY_WARNING);
356 config.function = "timeEnd";
357 config.expected_message = "Timer 'Test Message' does not exist";
358
359 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
360 handler->ExecuteTest();
361 ReleaseAndWaitForDestructor(handler);
362 }
363
TEST(DisplayTest,OnConsoleMessageInfo)364 TEST(DisplayTest, OnConsoleMessageInfo) {
365 ConsoleTestHandler::TestConfig config(LOGSEVERITY_INFO);
366 config.function = "info";
367
368 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
369 handler->ExecuteTest();
370 ReleaseAndWaitForDestructor(handler);
371 }
372
TEST(DisplayTest,OnConsoleMessageLog)373 TEST(DisplayTest, OnConsoleMessageLog) {
374 ConsoleTestHandler::TestConfig config(LOGSEVERITY_INFO);
375 config.function = "log";
376
377 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
378 handler->ExecuteTest();
379 ReleaseAndWaitForDestructor(handler);
380 }
381
TEST(DisplayTest,OnConsoleMessageGroup)382 TEST(DisplayTest, OnConsoleMessageGroup) {
383 ConsoleTestHandler::TestConfig config(LOGSEVERITY_INFO);
384 config.function = "group";
385
386 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
387 handler->ExecuteTest();
388 ReleaseAndWaitForDestructor(handler);
389 }
390
TEST(DisplayTest,OnConsoleMessageGroupCollapsed)391 TEST(DisplayTest, OnConsoleMessageGroupCollapsed) {
392 ConsoleTestHandler::TestConfig config(LOGSEVERITY_INFO);
393 config.function = "groupCollapsed";
394
395 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
396 handler->ExecuteTest();
397 ReleaseAndWaitForDestructor(handler);
398 }
399
TEST(DisplayTest,OnConsoleMessageGroupEnd)400 TEST(DisplayTest, OnConsoleMessageGroupEnd) {
401 ConsoleTestHandler::TestConfig config(LOGSEVERITY_INFO);
402 config.function = "groupEnd";
403
404 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
405 handler->ExecuteTest();
406 ReleaseAndWaitForDestructor(handler);
407 }
408
TEST(DisplayTest,OnConsoleMessageTable)409 TEST(DisplayTest, OnConsoleMessageTable) {
410 ConsoleTestHandler::TestConfig config(LOGSEVERITY_INFO);
411 config.function = "table";
412 config.message = "[1, 2, 3]";
413 config.expected_message = "1,2,3";
414
415 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
416 handler->ExecuteTest();
417 ReleaseAndWaitForDestructor(handler);
418 }
419
TEST(DisplayTest,OnConsoleMessageTrace)420 TEST(DisplayTest, OnConsoleMessageTrace) {
421 ConsoleTestHandler::TestConfig config(LOGSEVERITY_INFO);
422 config.function = "trace";
423 config.message = "";
424 config.expected_message = "console.trace";
425
426 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
427 handler->ExecuteTest();
428 ReleaseAndWaitForDestructor(handler);
429 }
430
TEST(DisplayTest,OnConsoleMessageWarn)431 TEST(DisplayTest, OnConsoleMessageWarn) {
432 ConsoleTestHandler::TestConfig config(LOGSEVERITY_WARNING);
433 config.function = "warn";
434
435 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
436 handler->ExecuteTest();
437 ReleaseAndWaitForDestructor(handler);
438 }
439
TEST(DisplayTest,OnConsoleMessageError)440 TEST(DisplayTest, OnConsoleMessageError) {
441 ConsoleTestHandler::TestConfig config(LOGSEVERITY_ERROR);
442 config.function = "error";
443
444 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
445 handler->ExecuteTest();
446 ReleaseAndWaitForDestructor(handler);
447 }
448
TEST(DisplayTest,OnConsoleMessageAssert)449 TEST(DisplayTest, OnConsoleMessageAssert) {
450 ConsoleTestHandler::TestConfig config(LOGSEVERITY_ERROR);
451 config.function = "assert";
452 config.message = "false";
453 config.expected_message = "console.assert";
454
455 CefRefPtr<ConsoleTestHandler> handler = new ConsoleTestHandler(config);
456 handler->ExecuteTest();
457 ReleaseAndWaitForDestructor(handler);
458 }
459
460 namespace {
461
462 const char kLoadinProgressUrl[] = "http://tests-display/loading-progress.html";
463
464 // Browser side.
465 class LoadingProgressTestHandler : public TestHandler {
466 public:
LoadingProgressTestHandler()467 LoadingProgressTestHandler() {}
468
RunTest()469 void RunTest() override {
470 // Add the resources that we will navigate to/from.
471 AddResource(kLoadinProgressUrl,
472 "<html><head><style>"
473 "body {overflow:hidden;margin:0px;padding:0px;}"
474 "</style></head><body><div id=a>Content</div></body></html>",
475 "text/html");
476
477 // Create the browser.
478 CreateBrowser(kLoadinProgressUrl);
479
480 // Time out the test after a reasonable period of time.
481 SetTestTimeout();
482 }
483
OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward)484 void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
485 bool isLoading,
486 bool canGoBack,
487 bool canGoForward) override {
488 if (isLoading)
489 return;
490
491 DestroyTest();
492 }
493
OnLoadingProgressChange(CefRefPtr<CefBrowser> browser,double progress)494 void OnLoadingProgressChange(CefRefPtr<CefBrowser> browser,
495 double progress) override {
496 if (!got_loading_progress_change0_) {
497 got_loading_progress_change0_.yes();
498 EXPECT_GE(progress, 0.0);
499 } else if (!got_loading_progress_change1_) {
500 got_loading_progress_change1_.yes();
501 EXPECT_LE(progress, 1.0);
502 }
503 }
504
DestroyTest()505 void DestroyTest() override {
506 EXPECT_TRUE(got_loading_progress_change0_);
507 EXPECT_TRUE(got_loading_progress_change1_);
508 TestHandler::DestroyTest();
509 }
510
511 private:
512 TrackCallback got_loading_progress_change0_;
513 TrackCallback got_loading_progress_change1_;
514
515 IMPLEMENT_REFCOUNTING(LoadingProgressTestHandler);
516 };
517
518 } // namespace
519
520 // Test OnLoadingProgressChange notification.
TEST(DisplayTest,LoadingProgress)521 TEST(DisplayTest, LoadingProgress) {
522 CefRefPtr<LoadingProgressTestHandler> handler =
523 new LoadingProgressTestHandler();
524 handler->ExecuteTest();
525 ReleaseAndWaitForDestructor(handler);
526 }
527