1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/webui/web_ui_test_handler.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "base/values.h" 11 #include "chrome/common/render_messages.h" 12 #include "chrome/test/base/ui_test_utils.h" 13 #include "content/public/browser/notification_details.h" 14 #include "content/public/browser/notification_registrar.h" 15 #include "content/public/browser/notification_types.h" 16 #include "content/public/browser/render_view_host.h" 17 #include "content/public/browser/web_contents.h" 18 #include "content/public/browser/web_ui.h" 19 20 using content::RenderViewHost; 21 22 WebUITestHandler::WebUITestHandler() 23 : test_done_(false), 24 test_succeeded_(false), 25 run_test_done_(false), 26 run_test_succeeded_(false), 27 is_waiting_(false) { 28 } 29 30 void WebUITestHandler::PreloadJavaScript(const string16& js_text, 31 RenderViewHost* preload_host) { 32 DCHECK(preload_host); 33 preload_host->Send(new ChromeViewMsg_WebUIJavaScript( 34 preload_host->GetRoutingID(), string16(), js_text, 0, 35 false)); 36 } 37 38 void WebUITestHandler::RunJavaScript(const string16& js_text) { 39 web_ui()->GetWebContents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame( 40 string16(), js_text); 41 } 42 43 bool WebUITestHandler::RunJavaScriptTestWithResult(const string16& js_text) { 44 test_succeeded_ = false; 45 run_test_succeeded_ = false; 46 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost(); 47 rvh->ExecuteJavascriptInWebFrameCallbackResult( 48 string16(), // frame_xpath 49 js_text, 50 base::Bind(&WebUITestHandler::JavaScriptComplete, 51 base::Unretained(this))); 52 return WaitForResult(); 53 } 54 55 void WebUITestHandler::RegisterMessages() { 56 web_ui()->RegisterMessageCallback("testResult", 57 base::Bind(&WebUITestHandler::HandleTestResult, base::Unretained(this))); 58 } 59 60 void WebUITestHandler::HandleTestResult(const ListValue* test_result) { 61 // Quit the message loop if |is_waiting_| so waiting process can get result or 62 // error. To ensure this gets done, do this before ASSERT* calls. 63 if (is_waiting_) 64 base::MessageLoopForUI::current()->Quit(); 65 66 SCOPED_TRACE("WebUITestHandler::HandleTestResult"); 67 68 EXPECT_FALSE(test_done_); 69 test_done_ = true; 70 test_succeeded_ = false; 71 72 ASSERT_TRUE(test_result->GetBoolean(0, &test_succeeded_)); 73 if (!test_succeeded_) { 74 std::string message; 75 ASSERT_TRUE(test_result->GetString(1, &message)); 76 LOG(ERROR) << message; 77 } 78 } 79 80 void WebUITestHandler::JavaScriptComplete(const base::Value* result) { 81 // Quit the message loop if |is_waiting_| so waiting process can get result or 82 // error. To ensure this gets done, do this before ASSERT* calls. 83 if (is_waiting_) 84 base::MessageLoopForUI::current()->Quit(); 85 86 SCOPED_TRACE("WebUITestHandler::JavaScriptComplete"); 87 88 EXPECT_FALSE(run_test_done_); 89 run_test_done_ = true; 90 run_test_succeeded_ = false; 91 92 ASSERT_TRUE(result->GetAsBoolean(&run_test_succeeded_)); 93 } 94 95 bool WebUITestHandler::WaitForResult() { 96 SCOPED_TRACE("WebUITestHandler::WaitForResult"); 97 test_done_ = false; 98 run_test_done_ = false; 99 is_waiting_ = true; 100 101 // Either sync test completion or the testDone() will cause message loop 102 // to quit. 103 content::RunMessageLoop(); 104 105 // Run a second message loop when not |run_test_done_| so that the sync test 106 // completes, or |run_test_succeeded_| but not |test_done_| so async tests 107 // complete. 108 if (!run_test_done_ || (run_test_succeeded_ && !test_done_)) { 109 content::RunMessageLoop(); 110 } 111 112 is_waiting_ = false; 113 114 // To succeed the test must execute as well as pass the test. 115 return run_test_succeeded_ && test_succeeded_; 116 } 117