OLD | NEW |
| (Empty) |
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/printing/print_dialog_cloud.h" | |
6 #include "chrome/browser/printing/print_dialog_cloud_internal.h" | |
7 | |
8 #include <functional> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/file_path.h" | |
12 #include "base/file_util.h" | |
13 #include "base/memory/singleton.h" | |
14 #include "base/path_service.h" | |
15 #include "base/threading/thread_restrictions.h" | |
16 #include "base/utf_string_conversions.h" | |
17 #include "base/values.h" | |
18 #include "chrome/browser/printing/cloud_print/cloud_print_url.h" | |
19 #include "chrome/browser/ui/browser_list.h" | |
20 #include "chrome/browser/ui/browser_window.h" | |
21 #include "chrome/browser/ui/webui/chrome_url_data_manager.h" | |
22 #include "chrome/common/chrome_paths.h" | |
23 #include "chrome/common/url_constants.h" | |
24 #include "chrome/test/base/in_process_browser_test.h" | |
25 #include "chrome/test/base/ui_test_utils.h" | |
26 #include "content/public/browser/notification_service.h" | |
27 #include "content/public/browser/notification_types.h" | |
28 #include "content/public/browser/render_view_host.h" | |
29 #include "content/public/browser/web_contents.h" | |
30 #include "content/test/test_browser_thread.h" | |
31 #include "net/url_request/url_request_filter.h" | |
32 #include "net/url_request/url_request_test_job.h" | |
33 #include "net/url_request/url_request_test_util.h" | |
34 #include "ui/ui_controls/ui_controls.h" | |
35 | |
36 using content::BrowserThread; | |
37 | |
38 namespace { | |
39 | |
40 class TestData { | |
41 public: | |
42 static TestData* GetInstance() { | |
43 return Singleton<TestData>::get(); | |
44 } | |
45 | |
46 const char* GetTestData() { | |
47 // Fetching this data blocks the IO thread, but we don't really care because | |
48 // this is a test. | |
49 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
50 | |
51 if (test_data_.empty()) { | |
52 FilePath test_data_directory; | |
53 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory); | |
54 FilePath test_file = | |
55 test_data_directory.AppendASCII("printing/cloud_print_uitest.html"); | |
56 file_util::ReadFileToString(test_file, &test_data_); | |
57 } | |
58 return test_data_.c_str(); | |
59 } | |
60 private: | |
61 TestData() {} | |
62 | |
63 std::string test_data_; | |
64 | |
65 friend struct DefaultSingletonTraits<TestData>; | |
66 }; | |
67 | |
68 // A simple test net::URLRequestJob. We don't care what it does, only that | |
69 // whether it starts and finishes. | |
70 class SimpleTestJob : public net::URLRequestTestJob { | |
71 public: | |
72 explicit SimpleTestJob(net::URLRequest* request) | |
73 : net::URLRequestTestJob(request, test_headers(), | |
74 TestData::GetInstance()->GetTestData(), true) {} | |
75 | |
76 virtual void GetResponseInfo(net::HttpResponseInfo* info) { | |
77 net::URLRequestTestJob::GetResponseInfo(info); | |
78 if (request_->url().SchemeIsSecure()) { | |
79 // Make up a fake certificate for this response since we don't have | |
80 // access to the real SSL info. | |
81 const char* kCertIssuer = "Chrome Internal"; | |
82 const int kLifetimeDays = 100; | |
83 | |
84 info->ssl_info.cert = | |
85 new net::X509Certificate(request_->url().GetWithEmptyPath().spec(), | |
86 kCertIssuer, | |
87 base::Time::Now(), | |
88 base::Time::Now() + | |
89 base::TimeDelta::FromDays(kLifetimeDays)); | |
90 info->ssl_info.cert_status = 0; | |
91 info->ssl_info.security_bits = -1; | |
92 } | |
93 } | |
94 | |
95 private: | |
96 ~SimpleTestJob() {} | |
97 }; | |
98 | |
99 class TestController { | |
100 public: | |
101 static TestController* GetInstance() { | |
102 return Singleton<TestController>::get(); | |
103 } | |
104 void set_result(bool value) { | |
105 result_ = value; | |
106 } | |
107 bool result() { | |
108 return result_; | |
109 } | |
110 void set_expected_url(const GURL& url) { | |
111 expected_url_ = url; | |
112 } | |
113 const GURL expected_url() { | |
114 return expected_url_; | |
115 } | |
116 void set_delegate(TestDelegate* delegate) { | |
117 delegate_ = delegate; | |
118 } | |
119 TestDelegate* delegate() { | |
120 return delegate_; | |
121 } | |
122 void set_use_delegate(bool value) { | |
123 use_delegate_ = value; | |
124 } | |
125 bool use_delegate() { | |
126 return use_delegate_; | |
127 } | |
128 private: | |
129 TestController() | |
130 : result_(false), | |
131 use_delegate_(false), | |
132 delegate_(NULL) {} | |
133 | |
134 bool result_; | |
135 bool use_delegate_; | |
136 GURL expected_url_; | |
137 TestDelegate* delegate_; | |
138 | |
139 friend struct DefaultSingletonTraits<TestController>; | |
140 }; | |
141 | |
142 } // namespace | |
143 | |
144 class PrintDialogCloudTest : public InProcessBrowserTest { | |
145 public: | |
146 PrintDialogCloudTest() : handler_added_(false) { | |
147 PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); | |
148 } | |
149 | |
150 // Must be static for handing into AddHostnameHandler. | |
151 static net::URLRequest::ProtocolFactory Factory; | |
152 | |
153 class AutoQuitDelegate : public TestDelegate { | |
154 public: | |
155 AutoQuitDelegate() {} | |
156 | |
157 virtual void OnResponseCompleted(net::URLRequest* request) { | |
158 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
159 MessageLoop::QuitClosure()); | |
160 } | |
161 }; | |
162 | |
163 virtual void SetUp() { | |
164 TestController::GetInstance()->set_result(false); | |
165 InProcessBrowserTest::SetUp(); | |
166 } | |
167 | |
168 virtual void TearDown() { | |
169 if (handler_added_) { | |
170 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); | |
171 filter->RemoveHostnameHandler(scheme_, host_name_); | |
172 handler_added_ = false; | |
173 TestController::GetInstance()->set_delegate(NULL); | |
174 } | |
175 InProcessBrowserTest::TearDown(); | |
176 } | |
177 | |
178 // Normally this is something I would expect could go into SetUp(), | |
179 // but there seems to be some timing or ordering related issue with | |
180 // the test harness that made that flaky. Calling this from the | |
181 // individual test functions seems to fix that. | |
182 void AddTestHandlers() { | |
183 if (!handler_added_) { | |
184 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); | |
185 GURL cloud_print_service_url = | |
186 CloudPrintURL(browser()->profile()). | |
187 GetCloudPrintServiceURL(); | |
188 scheme_ = cloud_print_service_url.scheme(); | |
189 host_name_ = cloud_print_service_url.host(); | |
190 filter->AddHostnameHandler(scheme_, host_name_, | |
191 &PrintDialogCloudTest::Factory); | |
192 handler_added_ = true; | |
193 | |
194 GURL cloud_print_dialog_url = | |
195 CloudPrintURL(browser()->profile()). | |
196 GetCloudPrintServiceDialogURL(); | |
197 TestController::GetInstance()->set_expected_url(cloud_print_dialog_url); | |
198 TestController::GetInstance()->set_delegate(&delegate_); | |
199 } | |
200 | |
201 CreateDialogForTest(); | |
202 } | |
203 | |
204 void CreateDialogForTest() { | |
205 FilePath path_to_pdf = | |
206 test_data_directory_.AppendASCII("printing/cloud_print_uitest.pdf"); | |
207 BrowserThread::PostTask( | |
208 BrowserThread::UI, FROM_HERE, | |
209 base::Bind(&internal_cloud_print_helpers::CreateDialogFullImpl, | |
210 path_to_pdf, string16(), string16(), | |
211 std::string("application/pdf"), true, false)); | |
212 } | |
213 | |
214 bool handler_added_; | |
215 std::string scheme_; | |
216 std::string host_name_; | |
217 FilePath test_data_directory_; | |
218 AutoQuitDelegate delegate_; | |
219 }; | |
220 | |
221 net::URLRequestJob* PrintDialogCloudTest::Factory(net::URLRequest* request, | |
222 const std::string& scheme) { | |
223 if (request && | |
224 (request->url() == TestController::GetInstance()->expected_url())) { | |
225 if (TestController::GetInstance()->use_delegate()) | |
226 request->set_delegate(TestController::GetInstance()->delegate()); | |
227 TestController::GetInstance()->set_result(true); | |
228 return new SimpleTestJob(request); | |
229 } | |
230 return new net::URLRequestTestJob(request, | |
231 net::URLRequestTestJob::test_headers(), | |
232 "", true); | |
233 } | |
234 | |
235 IN_PROC_BROWSER_TEST_F(PrintDialogCloudTest, HandlersRegistered) { | |
236 BrowserList::SetLastActive(browser()); | |
237 ASSERT_TRUE(BrowserList::GetLastActive()); | |
238 | |
239 AddTestHandlers(); | |
240 | |
241 TestController::GetInstance()->set_use_delegate(true); | |
242 | |
243 ui_test_utils::RunMessageLoop(); | |
244 | |
245 ASSERT_TRUE(TestController::GetInstance()->result()); | |
246 | |
247 // Close the dialog before finishing the test. | |
248 ui_test_utils::WindowedNotificationObserver tab_closed_observer( | |
249 content::NOTIFICATION_TAB_CLOSED, | |
250 content::NotificationService::AllSources()); | |
251 | |
252 // Can't use ui_test_utils::SendKeyPressSync or | |
253 // ui_test_utils::SendKeyPressAndWait due to a race condition with closing | |
254 // the window. See http://crbug.com/111269 | |
255 BrowserWindow* window = browser()->window(); | |
256 ASSERT_TRUE(window); | |
257 gfx::NativeWindow native_window = window->GetNativeHandle(); | |
258 ASSERT_TRUE(native_window); | |
259 bool key_sent = ui_controls::SendKeyPress(native_window, ui::VKEY_ESCAPE, | |
260 false, false, false, false); | |
261 EXPECT_TRUE(key_sent); | |
262 if (key_sent) | |
263 tab_closed_observer.Wait(); | |
264 } | |
OLD | NEW |