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.
5 #include "chrome/browser/printing/print_dialog_cloud.h"
6 #include "chrome/browser/printing/print_dialog_cloud_internal.h"
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/file_util.h"
14 #include "base/files/file_path.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/path_service.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/values.h"
20 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/url_constants.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "content/public/browser/notification_details.h"
25 #include "content/public/browser/notification_source.h"
26 #include "content/public/browser/notification_types.h"
27 #include "content/public/test/test_browser_thread.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 using content::BrowserThread
;
32 using content::WebContents
;
33 using content::WebUIMessageHandler
;
35 using testing::AtLeast
;
37 using testing::HasSubstr
;
38 using testing::IsNull
;
39 using testing::NotNull
;
40 using testing::Return
;
43 using ui::ExternalWebDialogUI
;
45 const char kPDFTestFile
[] = "printing/cloud_print_unittest.pdf";
46 const char kMockJobTitle
[] = "Mock Job Title";
47 const char kMockPrintTicket
[] = "Resolution=300";
50 base::FilePath
GetTestDataFileName() {
51 base::FilePath test_data_directory
;
52 PathService::Get(chrome::DIR_TEST_DATA
, &test_data_directory
);
53 base::FilePath test_file
= test_data_directory
.AppendASCII(kPDFTestFile
);
58 static std::string sTestFileData
;
59 if (sTestFileData
.empty()) {
60 base::FilePath test_file
= GetTestDataFileName();
61 base::ReadFileToString(test_file
, &sTestFileData
);
63 return &sTestFileData
[0];
66 MATCHER_P(StringValueEq
, expected
, "StringValue") {
67 if (expected
->Equals(&arg
))
69 std::string expected_string
, arg_string
;
70 expected
->GetAsString(&expected_string
);
71 arg
.GetAsString(&arg_string
);
72 *result_listener
<< "'" << arg_string
73 << "' (expected '" << expected_string
<< "')";
77 namespace internal_cloud_print_helpers
{
79 class MockCloudPrintFlowHandler
80 : public CloudPrintFlowHandler
,
81 public base::SupportsWeakPtr
<MockCloudPrintFlowHandler
> {
83 MockCloudPrintFlowHandler(const base::string16
& title
,
84 const base::string16
& print_ticket
,
85 const std::string
& file_type
)
86 : CloudPrintFlowHandler(NULL
, title
, print_ticket
, file_type
) {}
87 MOCK_METHOD0(DestructorCalled
, void());
88 MOCK_METHOD0(RegisterMessages
, void());
91 const content::NotificationSource
& source
,
92 const content::NotificationDetails
& details
));
93 MOCK_METHOD1(SetDialogDelegate
,
94 void(CloudPrintWebDialogDelegate
* delegate
));
95 MOCK_METHOD0(CreateCloudPrintDataSender
,
96 scoped_refptr
<CloudPrintDataSender
>());
99 class MockCloudPrintWebDialogDelegate
: public CloudPrintWebDialogDelegate
{
101 MOCK_CONST_METHOD0(GetDialogModalType
,
103 MOCK_CONST_METHOD0(GetDialogTitle
,
105 MOCK_CONST_METHOD0(GetDialogContentURL
,
107 MOCK_CONST_METHOD1(GetWebUIMessageHandlers
,
108 void(std::vector
<WebUIMessageHandler
*>* handlers
));
109 MOCK_CONST_METHOD1(GetDialogSize
,
110 void(gfx::Size
* size
));
111 MOCK_CONST_METHOD0(GetDialogArgs
,
113 MOCK_METHOD1(OnDialogClosed
,
114 void(const std::string
& json_retval
));
115 MOCK_METHOD2(OnCloseContents
,
116 void(WebContents
* source
, bool *out_close_dialog
));
119 } // namespace internal_cloud_print_helpers
121 using internal_cloud_print_helpers::CloudPrintDataSenderHelper
;
122 using internal_cloud_print_helpers::CloudPrintDataSender
;
124 class MockExternalWebDialogUI
: public ExternalWebDialogUI
{
126 MOCK_METHOD1(RenderViewCreated
,
127 void(content::RenderViewHost
* render_view_host
));
130 class MockCloudPrintDataSenderHelper
: public CloudPrintDataSenderHelper
{
132 // TODO(scottbyer): At some point this probably wants to use a
133 // MockTabContents instead of NULL, and to pre-load it with a bunch
134 // of expects/results.
135 MockCloudPrintDataSenderHelper() : CloudPrintDataSenderHelper(NULL
) {}
136 MOCK_METHOD3(CallJavascriptFunction
, void(const std::string
&,
137 const base::Value
& arg1
,
138 const base::Value
& arg2
));
141 class CloudPrintURLTest
: public testing::Test
{
143 CloudPrintURLTest() {}
146 virtual void SetUp() {
147 profile_
.reset(new TestingProfile());
150 scoped_ptr
<Profile
> profile_
;
153 TEST_F(CloudPrintURLTest
, CheckDefaultURLs
) {
154 std::string service_url
=
155 CloudPrintURL(profile_
.get()).
156 GetCloudPrintServiceURL().spec();
157 EXPECT_THAT(service_url
, HasSubstr("www.google.com"));
158 EXPECT_THAT(service_url
, HasSubstr("cloudprint"));
160 std::string dialog_url
=
161 CloudPrintURL(profile_
.get()).
162 GetCloudPrintServiceDialogURL().spec();
163 EXPECT_THAT(dialog_url
, HasSubstr("www.google.com"));
164 EXPECT_THAT(dialog_url
, HasSubstr("/cloudprint/"));
165 EXPECT_THAT(dialog_url
, HasSubstr("/client/"));
166 EXPECT_THAT(dialog_url
, Not(HasSubstr("cloudprint/cloudprint")));
167 EXPECT_THAT(dialog_url
, HasSubstr("/dialog.html"));
169 // Repeat to make sure there isn't a transient glitch.
171 CloudPrintURL(profile_
.get()).
172 GetCloudPrintServiceDialogURL().spec();
173 EXPECT_THAT(dialog_url
, HasSubstr("www.google.com"));
174 EXPECT_THAT(dialog_url
, HasSubstr("/cloudprint/"));
175 EXPECT_THAT(dialog_url
, HasSubstr("/client/"));
176 EXPECT_THAT(dialog_url
, Not(HasSubstr("cloudprint/cloudprint")));
177 EXPECT_THAT(dialog_url
, HasSubstr("/dialog.html"));
179 std::string manage_url
=
180 CloudPrintURL(profile_
.get()).
181 GetCloudPrintServiceManageURL().spec();
182 EXPECT_THAT(manage_url
, HasSubstr("www.google.com"));
183 EXPECT_THAT(manage_url
, HasSubstr("/cloudprint/"));
184 EXPECT_THAT(manage_url
, Not(HasSubstr("/client/")));
185 EXPECT_THAT(manage_url
, Not(HasSubstr("cloudprint/cloudprint")));
186 EXPECT_THAT(manage_url
, HasSubstr("/manage"));
188 GURL learn_more_url
= CloudPrintURL::GetCloudPrintLearnMoreURL();
189 std::string learn_more_path
= learn_more_url
.spec();
190 EXPECT_THAT(learn_more_path
, HasSubstr("www.google.com"));
191 EXPECT_THAT(learn_more_path
, HasSubstr("/support/"));
192 EXPECT_THAT(learn_more_path
, HasSubstr("/cloudprint"));
193 EXPECT_TRUE(learn_more_url
.has_path());
194 EXPECT_FALSE(learn_more_url
.has_query());
196 GURL test_page_url
= CloudPrintURL::GetCloudPrintTestPageURL();
197 std::string test_page_path
= test_page_url
.spec();
198 EXPECT_THAT(test_page_path
, HasSubstr("www.google.com"));
199 EXPECT_THAT(test_page_path
, HasSubstr("/landing/"));
200 EXPECT_THAT(test_page_path
, HasSubstr("/cloudprint/"));
201 EXPECT_TRUE(test_page_url
.has_path());
202 EXPECT_TRUE(test_page_url
.has_query());
205 // Testing for CloudPrintDataSender needs a mock WebUI.
206 class CloudPrintDataSenderTest
: public testing::Test
{
208 CloudPrintDataSenderTest()
209 : file_thread_(BrowserThread::FILE, &message_loop_
),
210 io_thread_(BrowserThread::IO
, &message_loop_
) {}
213 virtual void SetUp() {
214 mock_helper_
.reset(new MockCloudPrintDataSenderHelper
);
217 scoped_refptr
<CloudPrintDataSender
> CreateSender(
218 const base::RefCountedString
* data
) {
219 return new CloudPrintDataSender(mock_helper_
.get(),
220 base::ASCIIToUTF16(kMockJobTitle
),
221 base::ASCIIToUTF16(kMockPrintTicket
),
222 std::string("application/pdf"),
226 scoped_refptr
<CloudPrintDataSender
> print_data_sender_
;
227 scoped_ptr
<MockCloudPrintDataSenderHelper
> mock_helper_
;
229 base::MessageLoop message_loop_
;
230 content::TestBrowserThread file_thread_
;
231 content::TestBrowserThread io_thread_
;
234 TEST_F(CloudPrintDataSenderTest
, CanSend
) {
235 base::StringValue
mock_job_title(kMockJobTitle
);
236 EXPECT_CALL(*mock_helper_
,
237 CallJavascriptFunction(_
, _
, StringValueEq(&mock_job_title
))).
240 std::string
data("test_data");
241 scoped_refptr
<CloudPrintDataSender
> print_data_sender(
242 CreateSender(base::RefCountedString::TakeString(&data
)));
243 base::FilePath test_data_file_name
= GetTestDataFileName();
244 BrowserThread::PostTask(
245 BrowserThread::IO
, FROM_HERE
,
246 base::Bind(&CloudPrintDataSender::SendPrintData
, print_data_sender
));
247 base::MessageLoop::current()->RunUntilIdle();
250 TEST_F(CloudPrintDataSenderTest
, NoData
) {
251 EXPECT_CALL(*mock_helper_
, CallJavascriptFunction(_
, _
, _
)).Times(0);
253 scoped_refptr
<CloudPrintDataSender
> print_data_sender(CreateSender(NULL
));
254 base::FilePath test_data_file_name
= GetTestDataFileName();
255 BrowserThread::PostTask(
256 BrowserThread::IO
, FROM_HERE
,
257 base::Bind(&CloudPrintDataSender::SendPrintData
, print_data_sender
));
258 base::MessageLoop::current()->RunUntilIdle();
261 TEST_F(CloudPrintDataSenderTest
, EmptyData
) {
262 EXPECT_CALL(*mock_helper_
, CallJavascriptFunction(_
, _
, _
)).Times(0);
265 scoped_refptr
<CloudPrintDataSender
> print_data_sender(
266 CreateSender(base::RefCountedString::TakeString(&data
)));
267 base::FilePath test_data_file_name
= GetTestDataFileName();
268 BrowserThread::PostTask(
269 BrowserThread::IO
, FROM_HERE
,
270 base::Bind(&CloudPrintDataSender::SendPrintData
, print_data_sender
));
271 base::MessageLoop::current()->RunUntilIdle();
274 // Testing for CloudPrintFlowHandler needs a mock
275 // CloudPrintWebDialogDelegate, mock CloudPrintDataSender, and a mock
278 // Testing for CloudPrintWebDialogDelegate needs a mock
279 // CloudPrintFlowHandler.
281 using internal_cloud_print_helpers::MockCloudPrintFlowHandler
;
282 using internal_cloud_print_helpers::CloudPrintWebDialogDelegate
;
284 class CloudPrintWebDialogDelegateTest
: public testing::Test
{
286 CloudPrintWebDialogDelegateTest()
287 : ui_thread_(BrowserThread::UI
, &message_loop_
) {}
290 virtual void SetUp() {
291 base::string16 mock_title
;
292 base::string16 mock_print_ticket
;
293 std::string mock_file_type
;
294 MockCloudPrintFlowHandler
* handler
=
295 new MockCloudPrintFlowHandler(mock_print_ticket
, mock_title
,
297 mock_flow_handler_
= handler
->AsWeakPtr();
298 EXPECT_CALL(*mock_flow_handler_
.get(), SetDialogDelegate(_
));
299 EXPECT_CALL(*mock_flow_handler_
.get(), SetDialogDelegate(NULL
));
300 delegate_
.reset(new CloudPrintWebDialogDelegate(mock_flow_handler_
.get(),
304 virtual void TearDown() {
306 if (mock_flow_handler_
.get())
307 delete mock_flow_handler_
.get();
310 base::MessageLoopForUI message_loop_
;
311 content::TestBrowserThread ui_thread_
;
312 base::WeakPtr
<MockCloudPrintFlowHandler
> mock_flow_handler_
;
313 scoped_ptr
<CloudPrintWebDialogDelegate
> delegate_
;
316 TEST_F(CloudPrintWebDialogDelegateTest
, BasicChecks
) {
317 EXPECT_THAT(delegate_
->GetDialogContentURL().spec(),
318 StrEq(chrome::kChromeUICloudPrintResourcesURL
));
319 EXPECT_TRUE(delegate_
->GetDialogTitle().empty());
321 bool close_dialog
= false;
322 delegate_
->OnCloseContents(NULL
, &close_dialog
);
323 EXPECT_TRUE(close_dialog
);
326 TEST_F(CloudPrintWebDialogDelegateTest
, OwnedFlowDestroyed
) {
328 EXPECT_THAT(mock_flow_handler_
.get(), IsNull());
331 TEST_F(CloudPrintWebDialogDelegateTest
, UnownedFlowLetGo
) {
332 std::vector
<WebUIMessageHandler
*> handlers
;
333 delegate_
->GetWebUIMessageHandlers(&handlers
);
335 EXPECT_THAT(mock_flow_handler_
.get(), NotNull());
338 // Testing for ExternalWebDialogUI needs a mock WebContents and mock
339 // CloudPrintWebDialogDelegate (attached to the mock web_contents).
341 // Testing for PrintDialogCloud needs a mock Browser.