Home | History | Annotate | Download | only in printing
      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/files/file_path.h"
     14 #include "base/files/file_util.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 
     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 
     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:
     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.
    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:
    143   CloudPrintDataSenderTest()
    144       : file_thread_(BrowserThread::FILE, &message_loop_),
    145         io_thread_(BrowserThread::IO, &message_loop_) {}
    146 
    147  protected:
    148   virtual void SetUp() {
    149     mock_helper_.reset(new MockCloudPrintDataSenderHelper);
    150   }
    151 
    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 
    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 
    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 
    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:
    221   CloudPrintWebDialogDelegateTest()
    222       : ui_thread_(BrowserThread::UI, &message_loop_) {}
    223 
    224  protected:
    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 
    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 
    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 
    261 TEST_F(CloudPrintWebDialogDelegateTest, OwnedFlowDestroyed) {
    262   delegate_.reset();
    263   EXPECT_THAT(mock_flow_handler_.get(), IsNull());
    264 }
    265 
    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