downloads_dom_handler_browsertest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 19namespace { 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|. 25bool 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. 50class 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( 92 content::BrowserThread::UI, FROM_HERE, MessageLoop::QuitClosure()); 93 } 94 } 95 96 virtual void CallDownloadUpdated(const base::ListValue& download) OVERRIDE { 97 download_updated_.reset(download.DeepCopy()); 98 if (waiting_updated_) { 99 content::BrowserThread::PostTask( 100 content::BrowserThread::UI, FROM_HERE, MessageLoop::QuitClosure()); 101 } 102 } 103 104 private: 105 scoped_ptr<base::ListValue> downloads_list_; 106 scoped_ptr<base::ListValue> download_updated_; 107 bool waiting_list_; 108 bool waiting_updated_; 109 110 DISALLOW_COPY_AND_ASSIGN(MockDownloadsDOMHandler); 111}; 112 113} // namespace 114 115class DownloadsDOMHandlerTest : public InProcessBrowserTest { 116 public: 117 DownloadsDOMHandlerTest() {} 118 119 virtual ~DownloadsDOMHandlerTest() {} 120 121 virtual void SetUpOnMainThread() OVERRIDE { 122 mock_handler_.reset(new MockDownloadsDOMHandler(download_manager())); 123 CHECK(downloads_directory_.CreateUniqueTempDir()); 124 browser()->profile()->GetPrefs()->SetFilePath( 125 prefs::kDownloadDefaultDirectory, 126 downloads_directory_.path()); 127 CHECK(test_server()->Start()); 128 } 129 130 content::DownloadManager* download_manager() { 131 return content::BrowserContext::GetDownloadManager(browser()->profile()); 132 } 133 134 void DownloadAnItem() { 135 GURL url = test_server()->GetURL("files/downloads/image.jpg"); 136 std::vector<GURL> url_chain; 137 url_chain.push_back(url); 138 base::Time current(base::Time::Now()); 139 download_manager()->CreateDownloadItem( 140 base::FilePath(FILE_PATH_LITERAL("/path/to/file")), 141 base::FilePath(FILE_PATH_LITERAL("/path/to/file")), 142 url_chain, 143 GURL(std::string()), 144 current, 145 current, 146 128, 147 128, 148 content::DownloadItem::COMPLETE, 149 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, 150 content::DOWNLOAD_INTERRUPT_REASON_NONE, 151 false); 152 153 mock_handler_->WaitForDownloadsList(); 154 ASSERT_EQ(1, static_cast<int>(mock_handler_->downloads_list()->GetSize())); 155 EXPECT_TRUE(ListMatches( 156 mock_handler_->downloads_list(), 157 "[{\"file_externally_removed\": false," 158 " \"file_name\": \"file\"," 159 " \"id\": 0," 160 " \"otr\": false," 161 " \"since_string\": \"Today\"," 162 " \"state\": \"COMPLETE\"," 163 " \"total\": 128}]")); 164 } 165 166 protected: 167 scoped_ptr<MockDownloadsDOMHandler> mock_handler_; 168 169 private: 170 base::ScopedTempDir downloads_directory_; 171 172 DISALLOW_COPY_AND_ASSIGN(DownloadsDOMHandlerTest); 173}; 174 175// Tests removing all items, both when prohibited and when allowed. 176IN_PROC_BROWSER_TEST_F(DownloadsDOMHandlerTest, RemoveAll) { 177 DownloadAnItem(); 178 179 mock_handler_->reset_downloads_list(); 180 browser()->profile()->GetPrefs()->SetBoolean( 181 prefs::kAllowDeletingBrowserHistory, false); 182 mock_handler_->HandleClearAll(NULL); 183 mock_handler_->WaitForDownloadsList(); 184 ASSERT_EQ(1, static_cast<int>(mock_handler_->downloads_list()->GetSize())); 185 186 mock_handler_->reset_downloads_list(); 187 browser()->profile()->GetPrefs()->SetBoolean( 188 prefs::kAllowDeletingBrowserHistory, true); 189 mock_handler_->HandleClearAll(NULL); 190 mock_handler_->WaitForDownloadsList(); 191 EXPECT_EQ(0, static_cast<int>(mock_handler_->downloads_list()->GetSize())); 192} 193 194// Tests removing one item, both when prohibited and when allowed. 195IN_PROC_BROWSER_TEST_F(DownloadsDOMHandlerTest, RemoveOneItem) { 196 DownloadAnItem(); 197 base::ListValue item; 198 item.AppendInteger(0); 199 200 mock_handler_->reset_downloads_list(); 201 browser()->profile()->GetPrefs()->SetBoolean( 202 prefs::kAllowDeletingBrowserHistory, false); 203 mock_handler_->HandleRemove(&item); 204 // Removing an item only sends the new download list if anything was actually 205 // removed, so force it. 206 mock_handler_->ForceSendCurrentDownloads(); 207 mock_handler_->WaitForDownloadsList(); 208 ASSERT_EQ(1, static_cast<int>(mock_handler_->downloads_list()->GetSize())); 209 210 mock_handler_->reset_downloads_list(); 211 browser()->profile()->GetPrefs()->SetBoolean( 212 prefs::kAllowDeletingBrowserHistory, true); 213 mock_handler_->HandleRemove(&item); 214 mock_handler_->WaitForDownloadsList(); 215 EXPECT_EQ(0, static_cast<int>(mock_handler_->downloads_list()->GetSize())); 216} 217 218// Tests that DownloadsDOMHandler detects new downloads and relays them to the 219// renderer. 220// crbug.com/159390: This test fails when daylight savings time ends. 221IN_PROC_BROWSER_TEST_F(DownloadsDOMHandlerTest, DownloadsRelayed) { 222 DownloadAnItem(); 223 224 mock_handler_->WaitForDownloadUpdated(); 225 ASSERT_EQ(1, static_cast<int>(mock_handler_->download_updated()->GetSize())); 226 EXPECT_TRUE(ListMatches( 227 mock_handler_->download_updated(), 228 "[{\"file_externally_removed\": true," 229 " \"id\": 0}]")); 230 231 mock_handler_->reset_downloads_list(); 232 browser()->profile()->GetPrefs()->SetBoolean( 233 prefs::kAllowDeletingBrowserHistory, true); 234 mock_handler_->HandleClearAll(NULL); 235 mock_handler_->WaitForDownloadsList(); 236 EXPECT_EQ(0, static_cast<int>(mock_handler_->downloads_list()->GetSize())); 237} 238 239 240// TODO(benjhayden): Test the extension downloads filter for both 241// mock_handler_.downloads_list() and mock_handler_.download_updated(). 242 243// TODO(benjhayden): Test incognito, both downloads_list() and that on-record 244// calls can't access off-record items. 245 246// TODO(benjhayden): Test that bad download ids incoming from the javascript are 247// dropped on the floor. 248 249// TODO(benjhayden): Test that IsTemporary() downloads are not shown. 250 251// TODO(benjhayden): Test that RemoveObserver is called on all download items, 252// including items that crossed IsTemporary() and back. 253