- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / downloads_dom_handler_browsertest.cc
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 "base/auto_reset.h"
6 #include "base/files/scoped_temp_dir.h"
7 #include "base/json/json_reader.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/values.h"
10 #include "chrome/browser/history/download_row.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/webui/downloads_dom_handler.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/browser/web_contents.h"
18
19 namespace {
20
21 // Reads |right_json| into a ListValue |left_list|; returns true if all
22 // key-value pairs in in all dictionaries in |right_list| are also in the
23 // corresponding dictionary in |left_list|. Ignores keys in dictionaries in
24 // |left_list| that are not in the corresponding dictionary in |right_list|.
25 bool ListMatches(base::ListValue* left_list, const std::string& right_json) {
26   scoped_ptr<base::Value> right_value(base::JSONReader::Read(right_json));
27   base::ListValue* right_list = NULL;
28   CHECK(right_value->GetAsList(&right_list));
29   for (size_t i = 0; i < left_list->GetSize(); ++i) {
30     base::DictionaryValue* left_dict = NULL;
31     base::DictionaryValue* right_dict = NULL;
32     CHECK(left_list->GetDictionary(i, &left_dict));
33     CHECK(right_list->GetDictionary(i, &right_dict));
34     for (base::DictionaryValue::Iterator iter(*right_dict);
35           !iter.IsAtEnd(); iter.Advance()) {
36       base::Value* left_value = NULL;
37       if (left_dict->HasKey(iter.key()) &&
38           left_dict->Get(iter.key(), &left_value) &&
39           !iter.value().Equals(left_value)) {
40         LOG(WARNING) << iter.key();
41         return false;
42       }
43     }
44   }
45   return true;
46 }
47
48 // A |DownloadsDOMHandler| that doesn't use a real WebUI object, but is real in
49 // all other respects.
50 class MockDownloadsDOMHandler : public DownloadsDOMHandler {
51  public:
52   explicit MockDownloadsDOMHandler(content::DownloadManager* dlm)
53     : DownloadsDOMHandler(dlm),
54       waiting_list_(false),
55       waiting_updated_(false) {
56   }
57   virtual ~MockDownloadsDOMHandler() {}
58
59   base::ListValue* downloads_list() { return downloads_list_.get(); }
60   base::ListValue* download_updated() { return download_updated_.get(); }
61
62   void WaitForDownloadsList() {
63     if (downloads_list_.get())
64       return;
65     base::AutoReset<bool> reset_waiting(&waiting_list_, true);
66     content::RunMessageLoop();
67   }
68
69   void WaitForDownloadUpdated() {
70     if (download_updated_.get())
71       return;
72     base::AutoReset<bool> reset_waiting(&waiting_updated_, true);
73     content::RunMessageLoop();
74   }
75
76   void ForceSendCurrentDownloads() {
77     ScheduleSendCurrentDownloads();
78   }
79
80   void reset_downloads_list() { downloads_list_.reset(); }
81   void reset_download_updated() { download_updated_.reset(); }
82
83  protected:
84   virtual content::WebContents* GetWebUIWebContents() OVERRIDE {
85     return NULL;
86   }
87
88   virtual void CallDownloadsList(const base::ListValue& downloads) OVERRIDE {
89     downloads_list_.reset(downloads.DeepCopy());
90     if (waiting_list_) {
91       content::BrowserThread::PostTask(content::BrowserThread::UI,
92                                        FROM_HERE,
93                                        base::MessageLoop::QuitClosure());
94     }
95   }
96
97   virtual void CallDownloadUpdated(const base::ListValue& download) OVERRIDE {
98     download_updated_.reset(download.DeepCopy());
99     if (waiting_updated_) {
100       content::BrowserThread::PostTask(content::BrowserThread::UI,
101                                        FROM_HERE,
102                                        base::MessageLoop::QuitClosure());
103     }
104   }
105
106  private:
107   scoped_ptr<base::ListValue> downloads_list_;
108   scoped_ptr<base::ListValue> download_updated_;
109   bool waiting_list_;
110   bool waiting_updated_;
111
112   DISALLOW_COPY_AND_ASSIGN(MockDownloadsDOMHandler);
113 };
114
115 }  // namespace
116
117 class DownloadsDOMHandlerTest : public InProcessBrowserTest {
118  public:
119   DownloadsDOMHandlerTest() {}
120
121   virtual ~DownloadsDOMHandlerTest() {}
122
123   virtual void SetUpOnMainThread() OVERRIDE {
124     mock_handler_.reset(new MockDownloadsDOMHandler(download_manager()));
125     CHECK(downloads_directory_.CreateUniqueTempDir());
126     browser()->profile()->GetPrefs()->SetFilePath(
127         prefs::kDownloadDefaultDirectory,
128         downloads_directory_.path());
129     CHECK(test_server()->Start());
130   }
131
132   content::DownloadManager* download_manager() {
133     return content::BrowserContext::GetDownloadManager(browser()->profile());
134   }
135
136   void DownloadAnItem() {
137     GURL url = test_server()->GetURL("files/downloads/image.jpg");
138     std::vector<GURL> url_chain;
139     url_chain.push_back(url);
140     base::Time current(base::Time::Now());
141     download_manager()->CreateDownloadItem(
142         1, // id
143         base::FilePath(FILE_PATH_LITERAL("/path/to/file")),
144         base::FilePath(FILE_PATH_LITERAL("/path/to/file")),
145         url_chain,
146         GURL(std::string()),
147         current,
148         current,
149         std::string(),
150         std::string(),
151         128,
152         128,
153         content::DownloadItem::COMPLETE,
154         content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
155         content::DOWNLOAD_INTERRUPT_REASON_NONE,
156         false);
157
158     mock_handler_->WaitForDownloadsList();
159     ASSERT_EQ(1, static_cast<int>(mock_handler_->downloads_list()->GetSize()));
160     EXPECT_TRUE(ListMatches(
161         mock_handler_->downloads_list(),
162         "[{\"file_externally_removed\": false,"
163         "  \"file_name\": \"file\","
164         "  \"id\": 1,"
165         "  \"otr\": false,"
166         "  \"since_string\": \"Today\","
167         "  \"state\": \"COMPLETE\","
168         "  \"total\": 128}]"));
169   }
170
171  protected:
172   scoped_ptr<MockDownloadsDOMHandler> mock_handler_;
173
174  private:
175   base::ScopedTempDir downloads_directory_;
176
177   DISALLOW_COPY_AND_ASSIGN(DownloadsDOMHandlerTest);
178 };
179
180 // Tests removing all items, both when prohibited and when allowed.
181 IN_PROC_BROWSER_TEST_F(DownloadsDOMHandlerTest, RemoveAll) {
182   DownloadAnItem();
183
184   mock_handler_->reset_downloads_list();
185   browser()->profile()->GetPrefs()->SetBoolean(
186       prefs::kAllowDeletingBrowserHistory, false);
187   mock_handler_->HandleClearAll(NULL);
188   mock_handler_->WaitForDownloadsList();
189   ASSERT_EQ(1, static_cast<int>(mock_handler_->downloads_list()->GetSize()));
190
191   mock_handler_->reset_downloads_list();
192   browser()->profile()->GetPrefs()->SetBoolean(
193       prefs::kAllowDeletingBrowserHistory, true);
194   mock_handler_->HandleClearAll(NULL);
195   mock_handler_->WaitForDownloadsList();
196   EXPECT_EQ(0, static_cast<int>(mock_handler_->downloads_list()->GetSize()));
197 }
198
199 // Tests removing one item, both when prohibited and when allowed.
200 IN_PROC_BROWSER_TEST_F(DownloadsDOMHandlerTest, RemoveOneItem) {
201   DownloadAnItem();
202   base::ListValue item;
203   item.AppendInteger(1);
204
205   mock_handler_->reset_downloads_list();
206   browser()->profile()->GetPrefs()->SetBoolean(
207       prefs::kAllowDeletingBrowserHistory, false);
208   mock_handler_->HandleRemove(&item);
209   // Removing an item only sends the new download list if anything was actually
210   // removed, so force it.
211   mock_handler_->ForceSendCurrentDownloads();
212   mock_handler_->WaitForDownloadsList();
213   ASSERT_EQ(1, static_cast<int>(mock_handler_->downloads_list()->GetSize()));
214
215   mock_handler_->reset_downloads_list();
216   browser()->profile()->GetPrefs()->SetBoolean(
217       prefs::kAllowDeletingBrowserHistory, true);
218   mock_handler_->HandleRemove(&item);
219   mock_handler_->WaitForDownloadsList();
220   EXPECT_EQ(0, static_cast<int>(mock_handler_->downloads_list()->GetSize()));
221 }
222
223 // Tests that DownloadsDOMHandler detects new downloads and relays them to the
224 // renderer.
225 // crbug.com/159390: This test fails when daylight savings time ends.
226 IN_PROC_BROWSER_TEST_F(DownloadsDOMHandlerTest, DownloadsRelayed) {
227   DownloadAnItem();
228
229   mock_handler_->WaitForDownloadUpdated();
230   ASSERT_EQ(1, static_cast<int>(mock_handler_->download_updated()->GetSize()));
231   EXPECT_TRUE(ListMatches(
232       mock_handler_->download_updated(),
233       "[{\"file_externally_removed\": true,"
234       "  \"id\": 1}]"));
235
236   mock_handler_->reset_downloads_list();
237   browser()->profile()->GetPrefs()->SetBoolean(
238       prefs::kAllowDeletingBrowserHistory, true);
239   mock_handler_->HandleClearAll(NULL);
240   mock_handler_->WaitForDownloadsList();
241   EXPECT_EQ(0, static_cast<int>(mock_handler_->downloads_list()->GetSize()));
242 }
243
244
245 // TODO(benjhayden): Test the extension downloads filter for both
246 // mock_handler_.downloads_list() and mock_handler_.download_updated().
247
248 // TODO(benjhayden): Test incognito, both downloads_list() and that on-record
249 // calls can't access off-record items.
250
251 // TODO(benjhayden): Test that bad download ids incoming from the javascript are
252 // dropped on the floor.
253
254 // TODO(benjhayden): Test that IsTemporary() downloads are not shown.
255
256 // TODO(benjhayden): Test that RemoveObserver is called on all download items,
257 // including items that crossed IsTemporary() and back.