• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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_bind.h"
6 #include "include/test/cef_test_helpers.h"
7 #include "include/wrapper/cef_closure_task.h"
8 #include "tests/ceftests/test_handler.h"
9 #include "tests/gtest/include/gtest/gtest.h"
10 
11 namespace {
12 
13 const char* kStartUrl = "http://tests/JSDialogTestHandler.Start";
14 const char* kEndUrl = "http://tests/JSDialogTestHandler.End?r=";
15 
16 class JSDialogTestHandler : public TestHandler {
17  public:
18   enum TestType {
19     TYPE_ALERT,
20     TYPE_CONFIRM,
21     TYPE_PROMPT,
22     TYPE_ONBEFOREUNLOAD,
23   };
24   enum TestMode {
25     MODE_SUPPRESS,
26     MODE_RUN_IMMEDIATE,
27     MODE_RUN_DELAYED,
28   };
29 
JSDialogTestHandler(TestType type,TestMode mode,bool success,const std::string & user_input,const std::string & result)30   JSDialogTestHandler(TestType type,
31                       TestMode mode,
32                       bool success,
33                       const std::string& user_input,
34                       const std::string& result)
35       : type_(type),
36         mode_(mode),
37         success_(success),
38         user_input_(user_input),
39         result_(result) {}
40 
RunTest()41   void RunTest() override {
42     std::string content = "<html><head><body>START<script>";
43     if (type_ == TYPE_ALERT) {
44       content +=
45           "alert('My alert message'); "
46           "document.location='" +
47           std::string(kEndUrl) + "';";
48     } else if (type_ == TYPE_CONFIRM) {
49       content +=
50           "var r = confirm('My confirm message')?'ok':'cancel'; "
51           "document.location='" +
52           std::string(kEndUrl) + "'+r;";
53     } else if (type_ == TYPE_PROMPT) {
54       content +=
55           "var r = prompt('My prompt message','my default'); "
56           "document.location='" +
57           std::string(kEndUrl) + "'+r;";
58     } else if (type_ == TYPE_ONBEFOREUNLOAD) {
59       content +=
60           "window.onbeforeunload=function() {"
61           " return 'My unload message'; };";
62     }
63     content += "</script></body></html>";
64 
65     AddResource(kStartUrl, content, "text/html");
66     AddResource(kEndUrl, "<html><body>END</body></html>", "text/html");
67 
68     // Create the browser
69     CreateBrowser(kStartUrl);
70 
71     // Time out the test after a reasonable period of time.
72     SetTestTimeout();
73   }
74 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)75   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
76                  CefRefPtr<CefFrame> frame,
77                  int httpStatusCode) override {
78     if (!frame->IsMain())
79       return;
80 
81     std::string url = frame->GetURL();
82     if (url.find(kEndUrl) == 0) {
83       got_onloadend_.yes();
84 
85       std::string result = url.substr(strlen(kEndUrl));
86       EXPECT_STREQ(result_.c_str(), result.c_str());
87 
88       DestroyTest();
89     } else if (type_ == TYPE_ONBEFOREUNLOAD) {
90       // Send the page a user gesture to enable firing of the onbefureunload
91       // handler. See https://crbug.com/707007.
92       CefExecuteJavaScriptWithUserGestureForTests(frame, CefString());
93 
94       // Trigger the onunload handler.
95       frame->LoadURL(kEndUrl);
96     }
97   }
98 
Continue(CefRefPtr<CefJSDialogCallback> callback)99   void Continue(CefRefPtr<CefJSDialogCallback> callback) {
100     callback->Continue(success_, user_input_);
101   }
102 
OnJSDialog(CefRefPtr<CefBrowser> browser,const CefString & origin_url,JSDialogType dialog_type,const CefString & message_text,const CefString & default_prompt_text,CefRefPtr<CefJSDialogCallback> callback,bool & suppress_message)103   bool OnJSDialog(CefRefPtr<CefBrowser> browser,
104                   const CefString& origin_url,
105                   JSDialogType dialog_type,
106                   const CefString& message_text,
107                   const CefString& default_prompt_text,
108                   CefRefPtr<CefJSDialogCallback> callback,
109                   bool& suppress_message) override {
110     got_onjsdialog_.yes();
111 
112     EXPECT_STREQ(kStartUrl, origin_url.ToString().c_str());
113 
114     if (type_ == TYPE_ALERT) {
115       EXPECT_EQ(JSDIALOGTYPE_ALERT, dialog_type);
116       EXPECT_STREQ("My alert message", message_text.ToString().c_str());
117       EXPECT_TRUE(default_prompt_text.empty());
118     } else if (type_ == TYPE_CONFIRM) {
119       EXPECT_EQ(JSDIALOGTYPE_CONFIRM, dialog_type);
120       EXPECT_STREQ("My confirm message", message_text.ToString().c_str());
121       EXPECT_TRUE(default_prompt_text.empty());
122     } else if (type_ == TYPE_PROMPT) {
123       EXPECT_EQ(JSDIALOGTYPE_PROMPT, dialog_type);
124       EXPECT_STREQ("My prompt message", message_text.ToString().c_str());
125       EXPECT_STREQ("my default", default_prompt_text.ToString().c_str());
126     }
127 
128     EXPECT_FALSE(suppress_message);
129 
130     if (mode_ == MODE_SUPPRESS) {
131       // Suppress the dialog.
132       suppress_message = true;
133       return false;
134     } else if (mode_ == MODE_RUN_IMMEDIATE) {
135       // Continue immediately.
136       callback->Continue(success_, user_input_);
137     } else if (mode_ == MODE_RUN_DELAYED) {
138       // Continue asynchronously.
139       CefPostTask(TID_UI,
140                   base::Bind(&JSDialogTestHandler::Continue, this, callback));
141     }
142 
143     return true;
144   }
145 
OnBeforeUnloadDialog(CefRefPtr<CefBrowser> browser,const CefString & message_text,bool is_reload,CefRefPtr<CefJSDialogCallback> callback)146   bool OnBeforeUnloadDialog(CefRefPtr<CefBrowser> browser,
147                             const CefString& message_text,
148                             bool is_reload,
149                             CefRefPtr<CefJSDialogCallback> callback) override {
150     got_onbeforeunloaddialog_.yes();
151 
152     if (type_ == TYPE_ONBEFOREUNLOAD) {
153       // The message is no longer configurable via JavaScript.
154       // See http://crbug.com/587940.
155       EXPECT_STREQ("Is it OK to leave/reload this page?",
156                    message_text.ToString().c_str());
157       EXPECT_FALSE(is_reload);
158     }
159 
160     if (mode_ == MODE_RUN_IMMEDIATE) {
161       // Continue immediately.
162       callback->Continue(success_, user_input_);
163     } else if (mode_ == MODE_RUN_DELAYED) {
164       // Continue asynchronously.
165       CefPostTask(TID_UI,
166                   base::Bind(&JSDialogTestHandler::Continue, this, callback));
167     }
168 
169     return true;
170   }
171 
OnResetDialogState(CefRefPtr<CefBrowser> browser)172   void OnResetDialogState(CefRefPtr<CefBrowser> browser) override {
173     got_onresetdialogstate_.yes();
174   }
175 
176   TestType type_;
177   TestMode mode_;
178   bool success_;
179   std::string user_input_;
180   std::string result_;
181 
182   TrackCallback got_onjsdialog_;
183   TrackCallback got_onbeforeunloaddialog_;
184   TrackCallback got_onresetdialogstate_;
185   TrackCallback got_onloadend_;
186 
187   IMPLEMENT_REFCOUNTING(JSDialogTestHandler);
188 };
189 
190 }  // namespace
191 
192 // Alert dialog with suppression.
TEST(JSDialogTest,AlertSuppress)193 TEST(JSDialogTest, AlertSuppress) {
194   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
195       JSDialogTestHandler::TYPE_ALERT, JSDialogTestHandler::MODE_SUPPRESS,
196       true,  // success
197       "",    // user_input
198       "");   // result
199   handler->ExecuteTest();
200 
201   EXPECT_TRUE(handler->got_onjsdialog_);
202   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
203   EXPECT_TRUE(handler->got_onresetdialogstate_);
204   EXPECT_TRUE(handler->got_onloadend_);
205 
206   ReleaseAndWaitForDestructor(handler);
207 }
208 
209 // Alert dialog with immediate callback.
TEST(JSDialogTest,AlertRunImmediate)210 TEST(JSDialogTest, AlertRunImmediate) {
211   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
212       JSDialogTestHandler::TYPE_ALERT, JSDialogTestHandler::MODE_RUN_IMMEDIATE,
213       true,  // success
214       "",    // user_input
215       "");   // result
216   handler->ExecuteTest();
217 
218   EXPECT_TRUE(handler->got_onjsdialog_);
219   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
220   EXPECT_TRUE(handler->got_onresetdialogstate_);
221   EXPECT_TRUE(handler->got_onloadend_);
222 
223   ReleaseAndWaitForDestructor(handler);
224 }
225 
226 // Alert dialog with delayed callback.
TEST(JSDialogTest,AlertRunDelayed)227 TEST(JSDialogTest, AlertRunDelayed) {
228   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
229       JSDialogTestHandler::TYPE_ALERT, JSDialogTestHandler::MODE_RUN_DELAYED,
230       true,  // success
231       "",    // user_input
232       "");   // result
233   handler->ExecuteTest();
234 
235   EXPECT_TRUE(handler->got_onjsdialog_);
236   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
237   EXPECT_TRUE(handler->got_onresetdialogstate_);
238   EXPECT_TRUE(handler->got_onloadend_);
239 
240   ReleaseAndWaitForDestructor(handler);
241 }
242 
243 // Confirm dialog with suppression.
TEST(JSDialogTest,ConfirmSuppress)244 TEST(JSDialogTest, ConfirmSuppress) {
245   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
246       JSDialogTestHandler::TYPE_CONFIRM, JSDialogTestHandler::MODE_SUPPRESS,
247       true,       // success
248       "",         // user_input
249       "cancel");  // result
250   handler->ExecuteTest();
251 
252   EXPECT_TRUE(handler->got_onjsdialog_);
253   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
254   EXPECT_TRUE(handler->got_onresetdialogstate_);
255   EXPECT_TRUE(handler->got_onloadend_);
256 
257   ReleaseAndWaitForDestructor(handler);
258 }
259 
260 // Confirm dialog run immediately return OK.
TEST(JSDialogTest,ConfirmRunImmediateOk)261 TEST(JSDialogTest, ConfirmRunImmediateOk) {
262   CefRefPtr<JSDialogTestHandler> handler =
263       new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM,
264                               JSDialogTestHandler::MODE_RUN_IMMEDIATE,
265                               true,   // success
266                               "",     // user_input
267                               "ok");  // result
268   handler->ExecuteTest();
269 
270   EXPECT_TRUE(handler->got_onjsdialog_);
271   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
272   EXPECT_TRUE(handler->got_onresetdialogstate_);
273   EXPECT_TRUE(handler->got_onloadend_);
274 
275   ReleaseAndWaitForDestructor(handler);
276 }
277 
278 // Confirm dialog run immediately return Cancel.
TEST(JSDialogTest,ConfirmRunImmediateCancel)279 TEST(JSDialogTest, ConfirmRunImmediateCancel) {
280   CefRefPtr<JSDialogTestHandler> handler =
281       new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM,
282                               JSDialogTestHandler::MODE_RUN_IMMEDIATE,
283                               false,      // success
284                               "",         // user_input
285                               "cancel");  // result
286   handler->ExecuteTest();
287 
288   EXPECT_TRUE(handler->got_onjsdialog_);
289   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
290   EXPECT_TRUE(handler->got_onresetdialogstate_);
291   EXPECT_TRUE(handler->got_onloadend_);
292 
293   ReleaseAndWaitForDestructor(handler);
294 }
295 
296 // Confirm dialog run delayed return OK.
TEST(JSDialogTest,ConfirmRunDelayedOk)297 TEST(JSDialogTest, ConfirmRunDelayedOk) {
298   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
299       JSDialogTestHandler::TYPE_CONFIRM, JSDialogTestHandler::MODE_RUN_DELAYED,
300       true,   // success
301       "",     // user_input
302       "ok");  // result
303   handler->ExecuteTest();
304 
305   EXPECT_TRUE(handler->got_onjsdialog_);
306   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
307   EXPECT_TRUE(handler->got_onresetdialogstate_);
308   EXPECT_TRUE(handler->got_onloadend_);
309 
310   ReleaseAndWaitForDestructor(handler);
311 }
312 
313 // Confirm dialog run delayed return Cancel.
TEST(JSDialogTest,ConfirmRunDelayedCancel)314 TEST(JSDialogTest, ConfirmRunDelayedCancel) {
315   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
316       JSDialogTestHandler::TYPE_CONFIRM, JSDialogTestHandler::MODE_RUN_DELAYED,
317       false,      // success
318       "",         // user_input
319       "cancel");  // result
320   handler->ExecuteTest();
321 
322   EXPECT_TRUE(handler->got_onjsdialog_);
323   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
324   EXPECT_TRUE(handler->got_onresetdialogstate_);
325   EXPECT_TRUE(handler->got_onloadend_);
326 
327   ReleaseAndWaitForDestructor(handler);
328 }
329 
330 // Prompt dialog with suppression.
TEST(JSDialogTest,PromptSuppress)331 TEST(JSDialogTest, PromptSuppress) {
332   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
333       JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_SUPPRESS,
334       true,          // success
335       "some_value",  // user_input
336       "null");       // result
337   handler->ExecuteTest();
338 
339   EXPECT_TRUE(handler->got_onjsdialog_);
340   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
341   EXPECT_TRUE(handler->got_onresetdialogstate_);
342   EXPECT_TRUE(handler->got_onloadend_);
343 
344   ReleaseAndWaitForDestructor(handler);
345 }
346 
347 // Prompt dialog run immediately return OK.
TEST(JSDialogTest,PromptRunImmediateOk)348 TEST(JSDialogTest, PromptRunImmediateOk) {
349   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
350       JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_RUN_IMMEDIATE,
351       true,           // success
352       "some_value",   // user_input
353       "some_value");  // result
354   handler->ExecuteTest();
355 
356   EXPECT_TRUE(handler->got_onjsdialog_);
357   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
358   EXPECT_TRUE(handler->got_onresetdialogstate_);
359   EXPECT_TRUE(handler->got_onloadend_);
360 
361   ReleaseAndWaitForDestructor(handler);
362 }
363 
364 // Prompt dialog run immediately return Cancel.
TEST(JSDialogTest,PromptRunImmediateCancel)365 TEST(JSDialogTest, PromptRunImmediateCancel) {
366   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
367       JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_RUN_IMMEDIATE,
368       false,         // success
369       "some_value",  // user_input
370       "null");       // result
371   handler->ExecuteTest();
372 
373   EXPECT_TRUE(handler->got_onjsdialog_);
374   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
375   EXPECT_TRUE(handler->got_onresetdialogstate_);
376   EXPECT_TRUE(handler->got_onloadend_);
377 
378   ReleaseAndWaitForDestructor(handler);
379 }
380 
381 // Prompt dialog run delayed return OK.
TEST(JSDialogTest,PromptRunDelayedOk)382 TEST(JSDialogTest, PromptRunDelayedOk) {
383   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
384       JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_RUN_DELAYED,
385       true,           // success
386       "some_value",   // user_input
387       "some_value");  // result
388   handler->ExecuteTest();
389 
390   EXPECT_TRUE(handler->got_onjsdialog_);
391   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
392   EXPECT_TRUE(handler->got_onresetdialogstate_);
393   EXPECT_TRUE(handler->got_onloadend_);
394 
395   ReleaseAndWaitForDestructor(handler);
396 }
397 
398 // Prompt dialog run delayed return Cancel.
TEST(JSDialogTest,PromptRunDelayedCancel)399 TEST(JSDialogTest, PromptRunDelayedCancel) {
400   CefRefPtr<JSDialogTestHandler> handler = new JSDialogTestHandler(
401       JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_RUN_DELAYED,
402       false,         // success
403       "some_value",  // user_input
404       "null");       // result
405   handler->ExecuteTest();
406 
407   EXPECT_TRUE(handler->got_onjsdialog_);
408   EXPECT_FALSE(handler->got_onbeforeunloaddialog_);
409   EXPECT_TRUE(handler->got_onresetdialogstate_);
410   EXPECT_TRUE(handler->got_onloadend_);
411 
412   ReleaseAndWaitForDestructor(handler);
413 }
414 
415 // OnBeforeUnload dialog with immediate callback.
TEST(JSDialogTest,OnBeforeUnloadRunImmediate)416 TEST(JSDialogTest, OnBeforeUnloadRunImmediate) {
417   CefRefPtr<JSDialogTestHandler> handler =
418       new JSDialogTestHandler(JSDialogTestHandler::TYPE_ONBEFOREUNLOAD,
419                               JSDialogTestHandler::MODE_RUN_IMMEDIATE,
420                               true,  // success
421                               "",    // user_input
422                               "");   // result
423   handler->ExecuteTest();
424 
425   EXPECT_FALSE(handler->got_onjsdialog_);
426   EXPECT_TRUE(handler->got_onbeforeunloaddialog_);
427   EXPECT_TRUE(handler->got_onresetdialogstate_);
428   EXPECT_TRUE(handler->got_onloadend_);
429 
430   ReleaseAndWaitForDestructor(handler);
431 }
432 
433 // OnBeforeUnload dialog with delayed callback.
TEST(JSDialogTest,OnBeforeUnloadRunDelayed)434 TEST(JSDialogTest, OnBeforeUnloadRunDelayed) {
435   CefRefPtr<JSDialogTestHandler> handler =
436       new JSDialogTestHandler(JSDialogTestHandler::TYPE_ONBEFOREUNLOAD,
437                               JSDialogTestHandler::MODE_RUN_DELAYED,
438                               true,  // success
439                               "",    // user_input
440                               "");   // result
441   handler->ExecuteTest();
442 
443   EXPECT_FALSE(handler->got_onjsdialog_);
444   EXPECT_TRUE(handler->got_onbeforeunloaddialog_);
445   EXPECT_TRUE(handler->got_onresetdialogstate_);
446   EXPECT_TRUE(handler->got_onloadend_);
447 
448   ReleaseAndWaitForDestructor(handler);
449 }
450