• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
9 #include <vector>
10 
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/common/chrome_paths.h"
21 #include "chrome/common/url_constants.h"
22 #include "components/cloud_devices/common/cloud_devices_urls.h"
23 #include "content/public/browser/notification_details.h"
24 #include "content/public/browser/notification_source.h"
25 #include "content/public/browser/notification_types.h"
26 #include "content/public/test/test_browser_thread.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 
30 using content::BrowserThread;
31 using content::WebContents;
32 using content::WebUIMessageHandler;
33 using testing::A;
34 using testing::AtLeast;
35 using testing::Eq;
36 using testing::HasSubstr;
37 using testing::IsNull;
38 using testing::NotNull;
39 using testing::Return;
40 using testing::StrEq;
41 using testing::_;
42 using ui::ExternalWebDialogUI;
43 
44 const char kPDFTestFile[] = "printing/cloud_print_unittest.pdf";
45 const char kMockJobTitle[] = "Mock Job Title";
46 const char kMockPrintTicket[] = "Resolution=300";
47 
48 
GetTestDataFileName()49 base::FilePath GetTestDataFileName() {
50   base::FilePath test_data_directory;
51   PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory);
52   base::FilePath test_file = test_data_directory.AppendASCII(kPDFTestFile);
53   return test_file;
54 }
55 
GetTestData()56 char* GetTestData() {
57   static std::string sTestFileData;
58   if (sTestFileData.empty()) {
59     base::FilePath test_file = GetTestDataFileName();
60     base::ReadFileToString(test_file, &sTestFileData);
61   }
62   return &sTestFileData[0];
63 }
64 
65 MATCHER_P(StringValueEq, expected, "StringValue") {
66   if (expected->Equals(&arg))
67     return true;
68   std::string expected_string, arg_string;
69   expected->GetAsString(&expected_string);
70   arg.GetAsString(&arg_string);
71   *result_listener << "'" << arg_string
72                    << "' (expected '" << expected_string << "')";
73   return false;
74 }
75 
76 namespace internal_cloud_print_helpers {
77 
78 class MockCloudPrintFlowHandler
79     : public CloudPrintFlowHandler,
80       public base::SupportsWeakPtr<MockCloudPrintFlowHandler> {
81  public:
MockCloudPrintFlowHandler(const base::string16 & title,const base::string16 & print_ticket,const std::string & file_type)82   MockCloudPrintFlowHandler(const base::string16& title,
83                             const base::string16& print_ticket,
84                             const std::string& file_type)
85       : CloudPrintFlowHandler(NULL, title, print_ticket, file_type) {}
86   MOCK_METHOD0(DestructorCalled, void());
87   MOCK_METHOD0(RegisterMessages, void());
88   MOCK_METHOD3(Observe,
89                void(int type,
90                     const content::NotificationSource& source,
91                     const content::NotificationDetails& details));
92   MOCK_METHOD1(SetDialogDelegate,
93                void(CloudPrintWebDialogDelegate* delegate));
94   MOCK_METHOD0(CreateCloudPrintDataSender,
95                scoped_refptr<CloudPrintDataSender>());
96 };
97 
98 class MockCloudPrintWebDialogDelegate : public CloudPrintWebDialogDelegate {
99  public:
100   MOCK_CONST_METHOD0(GetDialogModalType,
101       ui::ModalType());
102   MOCK_CONST_METHOD0(GetDialogTitle,
103       base::string16());
104   MOCK_CONST_METHOD0(GetDialogContentURL,
105       GURL());
106   MOCK_CONST_METHOD1(GetWebUIMessageHandlers,
107       void(std::vector<WebUIMessageHandler*>* handlers));
108   MOCK_CONST_METHOD1(GetDialogSize,
109       void(gfx::Size* size));
110   MOCK_CONST_METHOD0(GetDialogArgs,
111       std::string());
112   MOCK_METHOD1(OnDialogClosed,
113       void(const std::string& json_retval));
114   MOCK_METHOD2(OnCloseContents,
115       void(WebContents* source, bool *out_close_dialog));
116 };
117 
118 }  // namespace internal_cloud_print_helpers
119 
120 using internal_cloud_print_helpers::CloudPrintDataSenderHelper;
121 using internal_cloud_print_helpers::CloudPrintDataSender;
122 
123 class MockExternalWebDialogUI : public ExternalWebDialogUI {
124  public:
125   MOCK_METHOD1(RenderViewCreated,
126                void(content::RenderViewHost* render_view_host));
127 };
128 
129 class MockCloudPrintDataSenderHelper : public CloudPrintDataSenderHelper {
130  public:
131   // TODO(scottbyer): At some point this probably wants to use a
132   // MockTabContents instead of NULL, and to pre-load it with a bunch
133   // of expects/results.
MockCloudPrintDataSenderHelper()134   MockCloudPrintDataSenderHelper() : CloudPrintDataSenderHelper(NULL) {}
135   MOCK_METHOD3(CallJavascriptFunction, void(const std::string&,
136                                             const base::Value& arg1,
137                                             const base::Value& arg2));
138 };
139 
140 // Testing for CloudPrintDataSender needs a mock WebUI.
141 class CloudPrintDataSenderTest : public testing::Test {
142  public:
CloudPrintDataSenderTest()143   CloudPrintDataSenderTest()
144       : file_thread_(BrowserThread::FILE, &message_loop_),
145         io_thread_(BrowserThread::IO, &message_loop_) {}
146 
147  protected:
SetUp()148   virtual void SetUp() {
149     mock_helper_.reset(new MockCloudPrintDataSenderHelper);
150   }
151 
CreateSender(const base::RefCountedString * data)152   scoped_refptr<CloudPrintDataSender> CreateSender(
153       const base::RefCountedString* data) {
154     return new CloudPrintDataSender(mock_helper_.get(),
155                                     base::ASCIIToUTF16(kMockJobTitle),
156                                     base::ASCIIToUTF16(kMockPrintTicket),
157                                     std::string("application/pdf"),
158                                     data);
159   }
160 
161   scoped_refptr<CloudPrintDataSender> print_data_sender_;
162   scoped_ptr<MockCloudPrintDataSenderHelper> mock_helper_;
163 
164   base::MessageLoop message_loop_;
165   content::TestBrowserThread file_thread_;
166   content::TestBrowserThread io_thread_;
167 };
168 
TEST_F(CloudPrintDataSenderTest,CanSend)169 TEST_F(CloudPrintDataSenderTest, CanSend) {
170   base::StringValue mock_job_title(kMockJobTitle);
171   EXPECT_CALL(*mock_helper_,
172               CallJavascriptFunction(_, _, StringValueEq(&mock_job_title))).
173       WillOnce(Return());
174 
175   std::string data("test_data");
176   scoped_refptr<CloudPrintDataSender> print_data_sender(
177       CreateSender(base::RefCountedString::TakeString(&data)));
178   base::FilePath test_data_file_name = GetTestDataFileName();
179   BrowserThread::PostTask(
180       BrowserThread::IO, FROM_HERE,
181       base::Bind(&CloudPrintDataSender::SendPrintData, print_data_sender));
182   base::MessageLoop::current()->RunUntilIdle();
183 }
184 
TEST_F(CloudPrintDataSenderTest,NoData)185 TEST_F(CloudPrintDataSenderTest, NoData) {
186   EXPECT_CALL(*mock_helper_, CallJavascriptFunction(_, _, _)).Times(0);
187 
188   scoped_refptr<CloudPrintDataSender> print_data_sender(CreateSender(NULL));
189   base::FilePath test_data_file_name = GetTestDataFileName();
190   BrowserThread::PostTask(
191       BrowserThread::IO, FROM_HERE,
192       base::Bind(&CloudPrintDataSender::SendPrintData, print_data_sender));
193   base::MessageLoop::current()->RunUntilIdle();
194 }
195 
TEST_F(CloudPrintDataSenderTest,EmptyData)196 TEST_F(CloudPrintDataSenderTest, EmptyData) {
197   EXPECT_CALL(*mock_helper_, CallJavascriptFunction(_, _, _)).Times(0);
198 
199   std::string data;
200   scoped_refptr<CloudPrintDataSender> print_data_sender(
201       CreateSender(base::RefCountedString::TakeString(&data)));
202   base::FilePath test_data_file_name = GetTestDataFileName();
203   BrowserThread::PostTask(
204       BrowserThread::IO, FROM_HERE,
205       base::Bind(&CloudPrintDataSender::SendPrintData, print_data_sender));
206   base::MessageLoop::current()->RunUntilIdle();
207 }
208 
209 // Testing for CloudPrintFlowHandler needs a mock
210 // CloudPrintWebDialogDelegate, mock CloudPrintDataSender, and a mock
211 // WebUI.
212 
213 // Testing for CloudPrintWebDialogDelegate needs a mock
214 // CloudPrintFlowHandler.
215 
216 using internal_cloud_print_helpers::MockCloudPrintFlowHandler;
217 using internal_cloud_print_helpers::CloudPrintWebDialogDelegate;
218 
219 class CloudPrintWebDialogDelegateTest : public testing::Test {
220  public:
CloudPrintWebDialogDelegateTest()221   CloudPrintWebDialogDelegateTest()
222       : ui_thread_(BrowserThread::UI, &message_loop_) {}
223 
224  protected:
SetUp()225   virtual void SetUp() {
226     base::string16 mock_title;
227     base::string16 mock_print_ticket;
228     std::string mock_file_type;
229     MockCloudPrintFlowHandler* handler =
230         new MockCloudPrintFlowHandler(mock_print_ticket, mock_title,
231                                       mock_file_type);
232     mock_flow_handler_ = handler->AsWeakPtr();
233     EXPECT_CALL(*mock_flow_handler_.get(), SetDialogDelegate(_));
234     EXPECT_CALL(*mock_flow_handler_.get(), SetDialogDelegate(NULL));
235     delegate_.reset(new CloudPrintWebDialogDelegate(mock_flow_handler_.get(),
236                                                     std::string()));
237   }
238 
TearDown()239   virtual void TearDown() {
240     delegate_.reset();
241     if (mock_flow_handler_.get())
242       delete mock_flow_handler_.get();
243   }
244 
245   base::MessageLoopForUI message_loop_;
246   content::TestBrowserThread ui_thread_;
247   base::WeakPtr<MockCloudPrintFlowHandler> mock_flow_handler_;
248   scoped_ptr<CloudPrintWebDialogDelegate> delegate_;
249 };
250 
TEST_F(CloudPrintWebDialogDelegateTest,BasicChecks)251 TEST_F(CloudPrintWebDialogDelegateTest, BasicChecks) {
252   EXPECT_THAT(delegate_->GetDialogContentURL().spec(),
253               StrEq(chrome::kChromeUICloudPrintResourcesURL));
254   EXPECT_TRUE(delegate_->GetDialogTitle().empty());
255 
256   bool close_dialog = false;
257   delegate_->OnCloseContents(NULL, &close_dialog);
258   EXPECT_TRUE(close_dialog);
259 }
260 
TEST_F(CloudPrintWebDialogDelegateTest,OwnedFlowDestroyed)261 TEST_F(CloudPrintWebDialogDelegateTest, OwnedFlowDestroyed) {
262   delegate_.reset();
263   EXPECT_THAT(mock_flow_handler_.get(), IsNull());
264 }
265 
TEST_F(CloudPrintWebDialogDelegateTest,UnownedFlowLetGo)266 TEST_F(CloudPrintWebDialogDelegateTest, UnownedFlowLetGo) {
267   std::vector<WebUIMessageHandler*> handlers;
268   delegate_->GetWebUIMessageHandlers(&handlers);
269   delegate_.reset();
270   EXPECT_THAT(mock_flow_handler_.get(), NotNull());
271 }
272 
273 // Testing for ExternalWebDialogUI needs a mock WebContents and mock
274 // CloudPrintWebDialogDelegate (attached to the mock web_contents).
275 
276 // Testing for PrintDialogCloud needs a mock Browser.
277