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