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