download_test_observer.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Copyright (c) 2012 The Chromium Authors. All rights reserved. 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Use of this source code is governed by a BSD-style license that can be 361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt// found in the LICENSE file. 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#include "content/public/test/download_test_observer.h" 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <vector> 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "base/bind.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "base/logging.h" 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "base/message_loop.h" 1261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "base/stl_util.h" 1361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "base/threading/sequenced_worker_pool.h" 1461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "content/public/browser/browser_thread.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "content/public/browser/download_url_parameters.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "content/public/test/test_utils.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "testing/gtest/include/gtest/gtest.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnamespace content { 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnamespace { 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt// These functions take scoped_refptr's to DownloadManager because they 2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt// are posted to message queues, and hence may execute arbitrarily after 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// their actual posting. Once posted, there is no connection between 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// these routines and the DownloadTestObserver class from which 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// they came, so the DownloadTestObserver's reference to the 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// DownloadManager cannot be counted on to keep the DownloadManager around. 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Fake user click on "Accept". 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid AcceptDangerousDownload(scoped_refptr<DownloadManager> download_manager, 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int32 download_id) { 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DownloadItem* download = download_manager->GetDownload(download_id); 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (download && (download->GetState() == DownloadItem::IN_PROGRESS)) 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt download->DangerousDownloadValidated(); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Fake user click on "Deny". 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid DenyDangerousDownload(scoped_refptr<DownloadManager> download_manager, 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int32 download_id) { 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DownloadItem* download = download_manager->GetDownload(download_id); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (download && (download->GetState() == DownloadItem::IN_PROGRESS)) { 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt download->Cancel(true); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt download->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD); 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} // namespace 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtDownloadUpdatedObserver::DownloadUpdatedObserver( 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DownloadItem* item, DownloadUpdatedObserver::EventFilter filter) 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt : item_(item), 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt filter_(filter), 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt waiting_(false), 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event_seen_(false) { 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt item->AddObserver(this); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtDownloadUpdatedObserver::~DownloadUpdatedObserver() { 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (item_) 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt item_->RemoveObserver(this); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtbool DownloadUpdatedObserver::WaitForEvent() { 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (item_ && filter_.Run(item_)) 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event_seen_ = true; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (event_seen_) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt waiting_ = true; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RunMessageLoop(); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt waiting_ = false; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return event_seen_; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid DownloadUpdatedObserver::OnDownloadUpdated(DownloadItem* item) { 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DCHECK_EQ(item_, item); 7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (filter_.Run(item_)) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event_seen_ = true; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (waiting_ && event_seen_) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MessageLoopForUI::current()->Quit(); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid DownloadUpdatedObserver::OnDownloadDestroyed(DownloadItem* item) { 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DCHECK_EQ(item_, item); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt item_->RemoveObserver(this); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt item_ = NULL; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (waiting_) 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MessageLoopForUI::current()->Quit(); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtDownloadTestObserver::DownloadTestObserver( 9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt DownloadManager* download_manager, 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t wait_count, 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DangerousDownloadAction dangerous_download_action) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt : download_manager_(download_manager), 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wait_count_(wait_count), 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt finished_downloads_at_construction_(0), 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt waiting_(false), 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dangerous_download_action_(dangerous_download_action) { 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtDownloadTestObserver::~DownloadTestObserver() { 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (DownloadSet::iterator it = downloads_observed_.begin(); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt it != downloads_observed_.end(); ++it) 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*it)->RemoveObserver(this); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt download_manager_->RemoveObserver(this); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid DownloadTestObserver::Init() { 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt download_manager_->AddObserver(this); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt std::vector<DownloadItem*> downloads; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt download_manager_->GetAllDownloads(&downloads); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (std::vector<DownloadItem*>::iterator it = downloads.begin(); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt it != downloads.end(); ++it) { 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt OnDownloadCreated(download_manager_, *it); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt finished_downloads_at_construction_ = finished_downloads_.size(); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt states_observed_.clear(); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid DownloadTestObserver::WaitForFinished() { 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!IsFinished()) { 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt waiting_ = true; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RunMessageLoop(); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt waiting_ = false; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtbool DownloadTestObserver::IsFinished() const { 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (finished_downloads_.size() - finished_downloads_at_construction_ >= 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wait_count_); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid DownloadTestObserver::OnDownloadCreated( 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DownloadManager* manager, 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DownloadItem* item) { 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // NOTE: This method is called both by DownloadManager when a download is 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // created as well as in DownloadTestObserver::Init() for downloads that 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // existed before |this| was created. 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt OnDownloadUpdated(item); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DownloadSet::const_iterator finished_it(finished_downloads_.find(item)); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // If it isn't finished, start observing it. 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (finished_it == finished_downloads_.end()) { 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt item->AddObserver(this); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt downloads_observed_.insert(item); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid DownloadTestObserver::OnDownloadDestroyed(DownloadItem* download) { 15261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // Stop observing. Do not do anything with it, as it is about to be gone. 15361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt DownloadSet::iterator it = downloads_observed_.find(download); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ASSERT_TRUE(it != downloads_observed_.end()); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt downloads_observed_.erase(it); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt download->RemoveObserver(this); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid DownloadTestObserver::OnDownloadUpdated(DownloadItem* download) { 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Real UI code gets the user's response after returning from the observer. 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (download->IsDangerous() && 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !ContainsKey(dangerous_downloads_seen_, download->GetId())) { 163 dangerous_downloads_seen_.insert(download->GetId()); 164 165 // Calling DangerousDownloadValidated() at this point will 166 // cause the download to be completed twice. Do what the real UI 167 // code does: make the call as a delayed task. 168 switch (dangerous_download_action_) { 169 case ON_DANGEROUS_DOWNLOAD_ACCEPT: 170 // Fake user click on "Accept". Delay the actual click, as the 171 // real UI would. 172 BrowserThread::PostTask( 173 BrowserThread::UI, FROM_HERE, 174 base::Bind(&AcceptDangerousDownload, download_manager_, 175 download->GetId())); 176 break; 177 178 case ON_DANGEROUS_DOWNLOAD_DENY: 179 // Fake a user click on "Deny". Delay the actual click, as the 180 // real UI would. 181 BrowserThread::PostTask( 182 BrowserThread::UI, FROM_HERE, 183 base::Bind(&DenyDangerousDownload, download_manager_, 184 download->GetId())); 185 break; 186 187 case ON_DANGEROUS_DOWNLOAD_FAIL: 188 ADD_FAILURE() << "Unexpected dangerous download item."; 189 break; 190 191 case ON_DANGEROUS_DOWNLOAD_IGNORE: 192 break; 193 194 default: 195 NOTREACHED(); 196 } 197 } 198 199 if (IsDownloadInFinalState(download)) 200 DownloadInFinalState(download); 201} 202 203size_t DownloadTestObserver::NumDangerousDownloadsSeen() const { 204 return dangerous_downloads_seen_.size(); 205} 206 207size_t DownloadTestObserver::NumDownloadsSeenInState( 208 DownloadItem::DownloadState state) const { 209 StateMap::const_iterator it = states_observed_.find(state); 210 211 if (it == states_observed_.end()) 212 return 0; 213 214 return it->second; 215} 216 217void DownloadTestObserver::DownloadInFinalState(DownloadItem* download) { 218 if (finished_downloads_.find(download) != finished_downloads_.end()) { 219 // We've already seen the final state on this download. 220 return; 221 } 222 223 // Record the transition. 224 finished_downloads_.insert(download); 225 226 // Record the state. 227 states_observed_[download->GetState()]++; // Initializes to 0 the first time. 228 229 SignalIfFinished(); 230} 231 232void DownloadTestObserver::SignalIfFinished() { 233 if (waiting_ && IsFinished()) 234 MessageLoopForUI::current()->Quit(); 235} 236 237DownloadTestObserverTerminal::DownloadTestObserverTerminal( 238 DownloadManager* download_manager, 239 size_t wait_count, 240 DangerousDownloadAction dangerous_download_action) 241 : DownloadTestObserver(download_manager, 242 wait_count, 243 dangerous_download_action) { 244 // You can't rely on overriden virtual functions in a base class constructor; 245 // the virtual function table hasn't been set up yet. So, we have to do any 246 // work that depends on those functions in the derived class constructor 247 // instead. In this case, it's because of |IsDownloadInFinalState()|. 248 Init(); 249} 250 251DownloadTestObserverTerminal::~DownloadTestObserverTerminal() { 252} 253 254 255bool DownloadTestObserverTerminal::IsDownloadInFinalState( 256 DownloadItem* download) { 257 return (download->GetState() != DownloadItem::IN_PROGRESS); 258} 259 260DownloadTestObserverInProgress::DownloadTestObserverInProgress( 261 DownloadManager* download_manager, 262 size_t wait_count) 263 : DownloadTestObserver(download_manager, 264 wait_count, 265 ON_DANGEROUS_DOWNLOAD_ACCEPT) { 266 // You can't override virtual functions in a base class constructor; the 267 // virtual function table hasn't been set up yet. So, we have to do any 268 // work that depends on those functions in the derived class constructor 269 // instead. In this case, it's because of |IsDownloadInFinalState()|. 270 Init(); 271} 272 273DownloadTestObserverInProgress::~DownloadTestObserverInProgress() { 274} 275 276 277bool DownloadTestObserverInProgress::IsDownloadInFinalState( 278 DownloadItem* download) { 279 return (download->GetState() == DownloadItem::IN_PROGRESS) && 280 !download->GetTargetFilePath().empty(); 281} 282 283DownloadTestFlushObserver::DownloadTestFlushObserver( 284 DownloadManager* download_manager) 285 : download_manager_(download_manager), 286 waiting_for_zero_inprogress_(true) {} 287 288void DownloadTestFlushObserver::WaitForFlush() { 289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 290 download_manager_->AddObserver(this); 291 // The wait condition may have been met before WaitForFlush() was called. 292 CheckDownloadsInProgress(true); 293 BrowserThread::GetBlockingPool()->FlushForTesting(); 294 RunMessageLoop(); 295} 296 297void DownloadTestFlushObserver::OnDownloadCreated( 298 DownloadManager* manager, 299 DownloadItem* item) { 300 CheckDownloadsInProgress(true); 301} 302 303void DownloadTestFlushObserver::OnDownloadDestroyed(DownloadItem* download) { 304 // Stop observing. Do not do anything with it, as it is about to be gone. 305 DownloadSet::iterator it = downloads_observed_.find(download); 306 ASSERT_TRUE(it != downloads_observed_.end()); 307 downloads_observed_.erase(it); 308 download->RemoveObserver(this); 309} 310 311void DownloadTestFlushObserver::OnDownloadUpdated(DownloadItem* download) { 312 // No change in DownloadItem set on manager. 313 CheckDownloadsInProgress(false); 314} 315 316DownloadTestFlushObserver::~DownloadTestFlushObserver() { 317 download_manager_->RemoveObserver(this); 318 for (DownloadSet::iterator it = downloads_observed_.begin(); 319 it != downloads_observed_.end(); ++it) { 320 (*it)->RemoveObserver(this); 321 } 322} 323 324// If we're waiting for that flush point, check the number 325// of downloads in the IN_PROGRESS state and take appropriate 326// action. If requested, also observes all downloads while iterating. 327void DownloadTestFlushObserver::CheckDownloadsInProgress( 328 bool observe_downloads) { 329 if (waiting_for_zero_inprogress_) { 330 int count = 0; 331 332 std::vector<DownloadItem*> downloads; 333 download_manager_->GetAllDownloads(&downloads); 334 for (std::vector<DownloadItem*>::iterator it = downloads.begin(); 335 it != downloads.end(); ++it) { 336 if ((*it)->GetState() == DownloadItem::IN_PROGRESS) 337 count++; 338 if (observe_downloads) { 339 if (downloads_observed_.find(*it) == downloads_observed_.end()) { 340 (*it)->AddObserver(this); 341 downloads_observed_.insert(*it); 342 } 343 // Download items are forever, and we don't want to make 344 // assumptions about future state transitions, so once we 345 // start observing them, we don't stop until destruction. 346 } 347 } 348 349 if (count == 0) { 350 waiting_for_zero_inprogress_ = false; 351 // Stop observing DownloadItems. We maintain the observation 352 // of DownloadManager so that we don't have to independently track 353 // whether we are observing it for conditional destruction. 354 for (DownloadSet::iterator it = downloads_observed_.begin(); 355 it != downloads_observed_.end(); ++it) { 356 (*it)->RemoveObserver(this); 357 } 358 downloads_observed_.clear(); 359 360 // Trigger next step. We need to go past the IO thread twice, as 361 // there's a self-task posting in the IO thread cancel path. 362 BrowserThread::PostTask( 363 BrowserThread::FILE, FROM_HERE, 364 base::Bind(&DownloadTestFlushObserver::PingFileThread, this, 2)); 365 } 366 } 367} 368 369void DownloadTestFlushObserver::PingFileThread(int cycle) { 370 BrowserThread::PostTask( 371 BrowserThread::IO, FROM_HERE, 372 base::Bind(&DownloadTestFlushObserver::PingIOThread, this, cycle)); 373} 374 375void DownloadTestFlushObserver::PingIOThread(int cycle) { 376 if (--cycle) { 377 BrowserThread::PostTask( 378 BrowserThread::UI, FROM_HERE, 379 base::Bind(&DownloadTestFlushObserver::PingFileThread, this, cycle)); 380 } else { 381 BrowserThread::PostTask( 382 BrowserThread::UI, FROM_HERE, MessageLoop::QuitClosure()); 383 } 384} 385 386DownloadTestItemCreationObserver::DownloadTestItemCreationObserver() 387 : download_id_(DownloadId::Invalid().local()), 388 error_(net::OK), 389 called_back_count_(0), 390 waiting_(false) { 391} 392 393DownloadTestItemCreationObserver::~DownloadTestItemCreationObserver() { 394} 395 396void DownloadTestItemCreationObserver::WaitForDownloadItemCreation() { 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 398 399 if (called_back_count_ == 0) { 400 waiting_ = true; 401 RunMessageLoop(); 402 waiting_ = false; 403 } 404} 405 406void DownloadTestItemCreationObserver::DownloadItemCreationCallback( 407 DownloadItem* item, 408 net::Error error) { 409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 410 411 if (item) 412 download_id_ = item->GetId(); 413 error_ = error; 414 ++called_back_count_; 415 DCHECK_EQ(1u, called_back_count_); 416 417 if (waiting_) 418 MessageLoopForUI::current()->Quit(); 419} 420 421const DownloadUrlParameters::OnStartedCallback 422 DownloadTestItemCreationObserver::callback() { 423 return base::Bind( 424 &DownloadTestItemCreationObserver::DownloadItemCreationCallback, this); 425} 426 427} // namespace content 428