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/plugins/plugin_installer.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "base/run_loop.h"
9#include "chrome/browser/plugins/plugin_installer_observer.h"
10#include "chrome/test/base/chrome_render_view_host_test_harness.h"
11#include "content/public/browser/download_url_parameters.h"
12#include "content/public/test/mock_download_item.h"
13#include "content/public/test/mock_download_manager.h"
14#include "testing/gmock/include/gmock/gmock.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17using ::testing::_;
18
19namespace {
20
21class PluginInstallerTest : public ChromeRenderViewHostTestHarness {
22 public:
23  PluginInstallerTest();
24  virtual void SetUp() OVERRIDE;
25  virtual void TearDown() OVERRIDE;
26
27  PluginInstaller* installer() { return installer_.get(); }
28
29  scoped_ptr<content::MockDownloadItem> CreateMockDownloadItem();
30
31 private:
32  scoped_ptr<PluginInstaller> installer_;
33};
34
35PluginInstallerTest::PluginInstallerTest() {
36}
37
38void PluginInstallerTest::SetUp() {
39  content::RenderViewHostTestHarness::SetUp();
40  installer_.reset(new PluginInstaller());
41}
42
43void PluginInstallerTest::TearDown() {
44  installer_.reset();
45  content::RenderViewHostTestHarness::TearDown();
46}
47
48scoped_ptr<content::MockDownloadItem>
49PluginInstallerTest::CreateMockDownloadItem() {
50  scoped_ptr<content::MockDownloadItem> mock_download_item(
51      new testing::StrictMock<content::MockDownloadItem>());
52  ON_CALL(*mock_download_item, GetState())
53      .WillByDefault(testing::Return(content::DownloadItem::IN_PROGRESS));
54  return mock_download_item.Pass();
55}
56
57class TestPluginInstallerObserver : public PluginInstallerObserver {
58 public:
59  explicit TestPluginInstallerObserver(PluginInstaller* installer)
60      : PluginInstallerObserver(installer),
61        download_started_(false),
62        download_finished_(false),
63        download_cancelled_(false) {}
64
65  bool download_started() const { return download_started_; }
66  bool download_finished() const { return download_finished_; }
67  bool download_cancelled() const { return download_cancelled_; }
68  const std::string& download_error() const { return download_error_; }
69
70 private:
71  virtual void DownloadStarted() OVERRIDE { download_started_ = true; }
72  virtual void DownloadFinished() OVERRIDE { download_finished_ = true; }
73  virtual void DownloadError(const std::string& message) OVERRIDE {
74    download_error_ = message;
75  }
76  virtual void DownloadCancelled() OVERRIDE { download_cancelled_ = true; }
77
78  bool download_started_;
79  bool download_finished_;
80  std::string download_error_;
81  bool download_cancelled_;
82};
83
84// Action for invoking the OnStartedCallback of DownloadURLParameters object
85// which is assumed to be pointed to by arg0.
86ACTION_P2(InvokeOnStartedCallback, download_item, interrupt_reason) {
87  arg0->callback().Run(download_item, interrupt_reason);
88}
89
90ACTION_P(InvokeClosure, closure) {
91  closure.Run();
92}
93
94const char kTestUrl[] = "http://example.com/some-url";
95
96}  // namespace
97
98// Test that DownloadStarted()/DownloadFinished() notifications are sent to
99// observers when a download initiated by PluginInstaller completes
100// successfully.
101TEST_F(PluginInstallerTest, StartInstalling_SuccessfulDownload) {
102  content::MockDownloadManager mock_download_manager;
103  base::RunLoop run_loop;
104  scoped_ptr<content::MockDownloadItem> download_item(CreateMockDownloadItem());
105
106  EXPECT_CALL(mock_download_manager,
107              DownloadUrlMock(testing::Property(
108                  &content::DownloadUrlParameters::url, GURL(kTestUrl))))
109      .WillOnce(testing::DoAll(
110          InvokeOnStartedCallback(download_item.get(),
111                                  content::DOWNLOAD_INTERRUPT_REASON_NONE),
112          InvokeClosure(run_loop.QuitClosure())));
113  EXPECT_CALL(*download_item, SetOpenWhenComplete(_));
114
115  TestPluginInstallerObserver installer_observer(installer());
116  installer()->StartInstallingWithDownloadManager(
117      GURL(kTestUrl), web_contents(), &mock_download_manager);
118  run_loop.Run();
119
120  EXPECT_TRUE(installer_observer.download_started());
121  EXPECT_FALSE(installer_observer.download_finished());
122
123  EXPECT_CALL(*download_item, GetState())
124      .WillOnce(testing::Return(content::DownloadItem::COMPLETE));
125  download_item->NotifyObserversDownloadUpdated();
126  EXPECT_TRUE(installer_observer.download_finished());
127}
128
129// Test that DownloadStarted()/DownloadError() notifications are sent to
130// observers when a download initiated by PluginInstaller fails to start.
131TEST_F(PluginInstallerTest, StartInstalling_FailedStart) {
132  content::MockDownloadManager mock_download_manager;
133  base::RunLoop run_loop;
134  scoped_ptr<content::MockDownloadItem> download_item(CreateMockDownloadItem());
135
136  EXPECT_CALL(mock_download_manager,
137              DownloadUrlMock(testing::Property(
138                  &content::DownloadUrlParameters::url, GURL(kTestUrl))))
139      .WillOnce(
140          testing::DoAll(InvokeOnStartedCallback(
141                             download_item.get(),
142                             content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED),
143                         InvokeClosure(run_loop.QuitClosure())));
144
145  TestPluginInstallerObserver installer_observer(installer());
146  installer()->StartInstallingWithDownloadManager(
147      GURL(kTestUrl), web_contents(), &mock_download_manager);
148  run_loop.Run();
149
150  EXPECT_TRUE(installer_observer.download_started());
151  EXPECT_FALSE(installer_observer.download_finished());
152  EXPECT_EQ("Error 20: NETWORK_FAILED", installer_observer.download_error());
153}
154
155// Test that DownloadStarted()/DownloadError() notifications are sent to
156// observers when a download initiated by PluginInstaller starts successfully
157// but is interrupted later.
158TEST_F(PluginInstallerTest, StartInstalling_Interrupted) {
159  content::MockDownloadManager mock_download_manager;
160  base::RunLoop run_loop;
161  scoped_ptr<content::MockDownloadItem> download_item(CreateMockDownloadItem());
162
163  EXPECT_CALL(mock_download_manager,
164              DownloadUrlMock(testing::Property(
165                  &content::DownloadUrlParameters::url, GURL(kTestUrl))))
166      .WillOnce(testing::DoAll(
167          InvokeOnStartedCallback(download_item.get(),
168                                  content::DOWNLOAD_INTERRUPT_REASON_NONE),
169          InvokeClosure(run_loop.QuitClosure())));
170  EXPECT_CALL(*download_item, SetOpenWhenComplete(_));
171
172  TestPluginInstallerObserver installer_observer(installer());
173  installer()->StartInstallingWithDownloadManager(
174      GURL(kTestUrl), web_contents(), &mock_download_manager);
175  run_loop.Run();
176
177  EXPECT_TRUE(installer_observer.download_started());
178  EXPECT_FALSE(installer_observer.download_finished());
179
180  EXPECT_CALL(*download_item, GetState())
181      .WillOnce(testing::Return(content::DownloadItem::INTERRUPTED));
182  EXPECT_CALL(*download_item, GetLastReason()).WillOnce(
183      testing::Return(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
184  download_item->NotifyObserversDownloadUpdated();
185
186  EXPECT_TRUE(installer_observer.download_started());
187  EXPECT_FALSE(installer_observer.download_finished());
188  EXPECT_EQ("NETWORK_FAILED", installer_observer.download_error());
189}
190